Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何使两个不兼容但成员相同的类型可互换?

如何使两个不兼容但成员相同的类型可互换?
EN

Stack Overflow用户
提问于 2010-03-19 08:36:18
回答 4查看 776关注 0票数 4

昨天,我们团队的两个家伙来找我,告诉我一个不常见的问题。我们在一个winforms应用程序中使用了第三方组件。所有的代码都是针对它编写的。然后,他们希望将同一供应商的另一个第三方组件合并到我们的应用程序中。令他们高兴的是,他们发现第二个组件与第一个组件具有完全相同的公共成员。但令他们沮丧的是,这两个组件具有完全独立的继承层次结构,并且没有实现公共接口。让你想知道..。这让我很好奇。

这个问题的一个例子:

Incompatible Types http://www.freeimagehosting.net/uploads/f9f6b862f1.png

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ThirdPartyClass1
{
    public string Name
    {
        get
        {
            return "ThirdPartyClass1";
        }
    }

    public void DoThirdPartyStuff ()
    {
        Console.WriteLine ("ThirdPartyClass1 is doing its thing.");
    }
}

public class ThirdPartyClass2
{
    public string Name
    {
        get
        {
            return "ThirdPartyClass2";
        }
    }

    public void DoThirdPartyStuff ()
    {
        Console.WriteLine ("ThirdPartyClass2 is doing its thing.");
    }
}

令人高兴的是,他们觉得复制和粘贴他们为第一个组件编写的代码并不是正确的答案。因此,他们正在考虑将组件即时赋值到对象引用中,然后在检查其类型后修改代码以进行条件强制转换。但这可以说比复制和粘贴方法更丑陋。

所以他们问我是否可以写一些反射代码来访问属性并调用两种不同的对象类型的方法,因为我们知道它们是什么,而且它们是完全相同的。但我的第一个想法是优雅消失了。我认为必须有一个更好、更优雅的解决方案来解决这个问题。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2010-03-19 08:41:36

我的第一个问题是,这两个第三方组件类是密封的吗?他们不是。至少我们有这一点。

因此,由于它们不是密封的,所以问题可以通过以下方式解决:

从两个第三方类的重合成员中提取一个公共接口。我叫它Icommon。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface ICommon
{
    string Name
    {
        get;
    }

    void DoThirdPartyStuff ();
}

然后创建两个新类:分别从ThirdPartyClass1和ThirdPartyClass2继承的DerivedClass1和DerivedClass2。这两个新类都实现了ICommon接口,但在其他方面都是完全空的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DerivedClass1
    : ThirdPartyClass1, ICommon
{
}

public class DerivedClass2
    : ThirdPartyClass2, ICommon
{
}

现在,即使派生类是空的,接口仍由基类满足,这是我们首先从基类中提取接口的地方。生成的类图如下所示。

alt text http://www.freeimagehosting.net/uploads/988cadf318.png

因此,现在,我们不再像以前那样:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ThirdPartyClass1 c1 = new ThirdPartyClass1 ();
c1. DoThirdPartyStuff ();

我们现在可以这样做:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
ICommon common = new DerivedClass1 ();
common. DoThirdPartyStuff ();

使用DerivedClass2也可以做到这一点。

其结果是,我们所有引用ThirdPartyClass1实例的现有代码都可以保持原样,只需将ThirdPartyClass1引用换成ICommon引用即可。然后,可以为ICommon引用提供DerivedClass1或DerivedClass2的实例,这两个实例分别从ThirdPartyClass1和ThirdPartyClass2继承。一切都很好用。

我不知道这是否有一个特定的名称,但对我来说,它看起来像是适配器模式的变体。

也许我们可以用C# 4.0中的动态类型来解决这个问题,但这不会带来编译时检查的好处。

我很想知道是否有人有解决这个问题的另一种优雅的方法。

票数 12
EN

Stack Overflow用户

发布于 2010-03-19 09:04:55

如果你使用的是.Net 4,你可以避免做很多这样的事情,因为动态类型可以帮助你做你想要的事情。但是,如果使用.Net 2+,还有另一种(不同的方式)来实现这一点:

您可以使用类似于Deft Flux的鸭子类型库来处理您的第三方类,就好像它们实现了一个接口一样。

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface ICommonInterface
{
    string Name { get; }
    void DoThirdPartyStuff();
}

//...in your code:
ThirdPartyClass1 classWeWishHadInterface = new ThirdPartyClass1()
ICommonInterface classWrappedAsInterface = DuckTyping.Cast<ICommonInterface>(classWeWishHadInterface);

classWrappedAsInterface.DoThirdPartyStuff();

这就避免了必须为所有这些类手动构建派生包装类,并且只要类具有与接口相同的成员就可以工作

票数 4
EN

Stack Overflow用户

发布于 2010-03-19 08:40:42

一些包装纸怎么样?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class ThirdPartyClass1 {
    public string Name {
        get {
            return "ThirdPartyClass1";
        }
    }

    public void DoThirdPartyStuff() {
        Console.WriteLine("ThirdPartyClass1 is doing its thing.");
    }
}

public interface IThirdPartyClassWrapper {
    public string Name { get; }
    public void DoThirdPartyStuff();
}

public class ThirdPartyClassWrapper1 : IThirdPartyClassWrapper {

    ThirdPartyClass1 _thirdParty;

    public string Name {
        get { return _thirdParty.Name; }
    }

    public void DoThirdPartyStuff() {
        _thirdParty.DoThirdPartyStuff();
    }
}

对ThirdPartyClass2使用相同的包装器,然后在所有方法中使用...and接口。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2475920

复制
相关文章
C语言 | 顺序排号
这道理放在C语言学习上也一并受用。在编程方面有着天赋异禀的人毕竟是少数,我们大多数人想要从C语言小白进阶到高手,需要经历的是日积月累的学习。
小林C语言
2021/03/10
6710
C语言_数字排列顺序
1 #include <stdio.h> 2 #include <stdlib.h> 3 #define LENGTH 8 4 5 void main() { 6 int i, j, tmp, number[LENGTH] = { 95, 45, 15, 78, 84, 51, 24, 12 }; 7 8 for (i = 0; i < LENGTH; i++) { 9 for (j = LENGTH - 1; j > i; j--) { 10
landv
2018/05/24
2.7K0
C语言实现顺序队列
顺序队列和顺序栈相类似,在队列的顺序存储结构中,除了用一组地址连续的存储单元依次存放从队列头到队列尾的元素之外,尚需附设两个 “指针” front 和 rear 分别指示队列头元素及队列尾元素的位置。
忆想不到的晖
2020/07/15
1.7K0
C语言实现顺序队列
C语言--顺序表的实现
#include<stdio.h> #define list_init_size 100 typedef struct{ int data[list_init_size]; int length; }Seqlist; void creat(Seqlist &L);//建立线性表 void show(Seqlist L);//显示线性表 void insert(Seqlist &L,int position,int e); //插入数据e,位置为position void so
王也518
2022/10/26
1.4K0
Go 语言 map 如何顺序读取?
Go 语言中的 map 是一种非常强大的数据结构,它允许我们快速地存储和检索键值对。
AlwaysBeta
2023/05/27
5830
顺序表C语言实现
头文件 list.h #define MaxSize 50 //表长度的初始定义 typedef struct{ ElemType data[MaxSize]; //顺序表的元素 int length; //顺序表的当前长度 }SqList; //顺 序表的类型定义 //初始化 int Initiate(SqList &L) { L.length=0; return 1; } //插入函数 bool ListInsert(SqList &L,in
别团等shy哥发育
2023/02/27
1.5K0
顺序表C语言实现
C/C++常用算法【C语言顺序查找(顺序表)】【2】
顺序表结构的存储方式非常容易理解,操作也十分方便。但是顺序表结构有如下一些缺点: 1.在插入或者删除结点时,往往需要移动大量的数据。 2.如果表比较大,有时难以分配足够的连续存储空间,往往导致内存分配失败,而无法存储。 后面会有链表结构的章节。
谙忆
2021/01/20
1.1K0
C/C++常用算法【C语言顺序查找(顺序表)】【2】
C语言 | 顺序向后移动
这道理放在C语言学习上也一并受用。在编程方面有着天赋异禀的人毕竟是少数,我们大多数人想要从C语言小白进阶到高手,需要经历的是日积月累的学习。
小林C语言
2021/03/10
7890
C语言实现顺序栈
源代码已上传到 GitHub Data-Structure-of-C,欢迎大家下载 C语言实现数据结构
忆想不到的晖
2020/07/15
5.4K1
C语言实现顺序栈
C语言"陷阱" 之运算顺序
在C语言中,某些运算符总是以一种已知的、规定的运算顺序对其操作数进行求值,而另外一些则不是这样。考虑如下表达式:
开源519
2020/07/23
7690
C语言"陷阱" 之运算顺序
M语言编程_所有编程语言大全
一直对技术有很强的兴趣,终于,决定要写自己的语言(m语言)。那就先从最简单的开始:解释执行器。
全栈程序员站长
2022/09/20
13K0
plsql编程语言_编程语言有哪些
–pl/sql编程语言 –pl/sql编程语言是对sql语言的扩展,是的sql语言具有过程化编程的特性 –pl/sql编程语言比一般的过程化编程语言,更加灵活高效 –pl/sql编程语言主要用来编写存储过程和存储函数等。
全栈程序员站长
2022/09/27
13.1K0
无锁编程(六) - seqlock(顺序锁)
seqlock(顺序锁) 用于能够区分读与写的场合,并且是读操作很多、写操作很少,写操作的优先权大于读操作。 seqlock的实现思路是,用一个递增的整型数表示sequence。写操作进入临界区时,sequence++;退出临界区时,sequence再++。写操作还需要获得一个锁(比如mutex),这个锁仅用于写写互斥,以保证同一时间最多只有一个正在进行的写操作。 当sequence为奇数时,表示有写操作正在进行,这时读操作要进入临界区需要等待,直到sequence变为偶数。读操作进入临界区时,需要记录
三丰SanFeng
2018/01/16
1.7K0
6.计算机语言的发展 编程语言发展 编程语言类型 为什么会有编程语言 编程语言什么作用 机器语言 高级语言分类 编程语言历史 编程语言有哪些 编程语言编年史
随后,开始用与代码指令实际含义相近的英文缩写词、字母和数字等符号来替代描述指令代码
noteless
2018/09/11
15.4K0
6.计算机语言的发展   编程语言发展 编程语言类型 为什么会有编程语言 编程语言什么作用 机器语言 高级语言分类  编程语言历史  编程语言有哪些 编程语言编年史
C语言函数求参数顺序问题
对于函数func,先求右边x+=2参数,返回x=8,然后计算结果。也就是传递给形参的两个值都是8,返回值为16。
用户6755376
2019/11/19
2.5K0
硬件描述语言VHDL——顺序语句
版权声明:本文为博主原创文章,转载请注明博客地址: https://blog.csdn.net/zy010101/article/details/88685089
zy010101
2019/05/25
2.2K0
顺序循环队列(C语言实现)
头文件: Queue.h typedef struct { DataType queue[MaxQueueSize]; int rear; //队尾指针 int front; //队头指针 int count; //计数器 }SeqQueue; //初始化 void Q
别团等shy哥发育
2023/02/27
7210
顺序循环队列(C语言实现)
用c语言实现顺序表_顺序表代码讲解以及实现
1、 创建顺序表 2、 按数值查找 3、 按位置查找 4、 插一个数值 5、 删一个数值 6、 销毁顺序表 7、 求前驱算法 8、 求后继算法
全栈程序员站长
2022/11/15
1.9K0
人类语言遇上编程语言
自然语言(人类语言)与编程语言之间有着很多惊人的相似之处。前些天我做了一个关于这两种语言相似性的讨论,惊讶地发现自己很容易就找到了它们之间的许多共同点。 然而实际上,两种语言之间具有如此多的相同之处也尚在情理之中,这两种形式的语言都是非常基础层面上的语言,它们本质上是为同一个目的服务的——那就是沟通。尤其是用来沟通思想和表达方式,有时也可以用来传达指令。 编程语言之间的相似之处比人们乍看上去的还要多得多。这意味着如果你很了解某一门编程语言,学习其他编程语言(至少同类型的编程语言)就变得十分容易。最开始的两种
程序员互动联盟
2018/03/13
10.9K0
点击加载更多

相似问题

编程语言中的字节顺序

30

所有编程语言都是按顺序读取的吗?

35

C语言中的字节顺序和套接字编程

12

文本编程语言与图形编程语言

2422

编程语言

41
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文