假设您有两个不同的C#类A
和B
,虽然不是从相同的基类派生,但是为方法共享一些相同的名称。例如,两个类都有connect
和disconnect
方法,以及其他几个类。我希望能够编写一次适用于这两种类型的代码。
以下是我想要做的简化示例:
public void make_connection(Object x)
{
x.connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
当然,这不会编译,因为Object类没有connect
或disconnect
方法。
有办法做到这一点吗?
更新。我应该从一开始就明确这一点:我只有A和B的DLL,而不是源代码。
答案 0 :(得分:26)
您可以使用界面来完成您想要做的事情。
interface IConnectable
{
void Connect();
void Disconnect();
}
A
和B
都应该实现IConnectable
。然后使用IConnectable
代替Object
作为方法的参数类型,您应该全部设置。
public void MakeConnection(IConnectable connectable)
{
connectable.Connect();
// Do some more stuff...
connectable.Disconnect();
}
修改:由于您没有源代码,因此您有以下几种选择:
dynamic
关键字解决方案(如果您使用的是.NET 4.0)if
/ else
语句A
和B
创建包装类,让它们实现接口(或者为它们使用通用的抽象基类)例如:
class AWrapper : IConnectable
{
private A obj;
public AWrapper(A obj)
{
this.obj = obj;
}
public void Connect()
{
this.obj.Connect();
}
public void Disconnect()
{
this.obj.Disconnect();
}
// other methods as necessary
}
(BWrapper
类似,仅使用B
代替A
)
然后你可以创建包装器并将它们传递给MakeConnection
。这取决于你想要的方式。根据您的情况,一种方法可能比其他方法更容易。
答案 1 :(得分:11)
这适用于C#4:
public void make_connection(dynamic x)
{
x.connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
答案 2 :(得分:2)
尝试使用界面。
查看interface (C# Reference)和Interfaces (C# Programming Guide)
类似
public interface IConnections
{
void connect();
void disconnect();
}
public class A : IConnections
{
public void connect()
{
//do something
}
public void disconnect()
{
//do something
}
}
public class B : IConnections
{
public void connect()
{
//do something
}
public void disconnect()
{
//do something
}
}
public void make_connection(IConnections x)
{
x.connect();
// Do some more stuff...
x.disconnect();
return;
}
答案 3 :(得分:1)
有一个OOAD概念'Programe到一个接口而不是一个实现',这让你避免了继承层次结构链
1-您可以创建一个interfcae
interface IConnection
{
void Connect();
void Disconnect();
}
2-让你的类实现这个界面,如下所示。
class A : IConnection
{
#region IConnection Members
public void Connect()
{
// your connect method implementation goes here.
}
public void Disconnect()
{
// your disconnect method implementation goes here.
}
#endregion
}
class B : IConnection
{
#region IConnection Members
public void Connect()
{
// your connect method implementation goes here.
}
public void Disconnect()
{
// your disconnect method implementation goes here.
}
#endregion
}
3-完成实现后,您可以使函数接受IConnection的参数,如下所示。
public void makeConnection(IConnection con)
{
con.Connect();
con.Disconnect();
}
4-从客户端代码中,您可以传递实现IConnect接口的类的对象。
答案 4 :(得分:1)
如果无法使用接口解决方案(例如,您没有源代码),另一种效率较低的解决方案是使用反射。
答案 5 :(得分:1)
正如其他人所说,重新分解使用接口或使用动态方法可能是最优雅的方式。
如果无法做到这一点,您可以将对象强制转换为类型。我建议使用as
,然后检查演员是否有效,如果某人使用无法演员的类型调用此演员,那么未经检查的演员会很危险。
E.g。如果类型A
和B
都有一个名为DoSomething()
的方法,那么这将有效......
public static void CallDoSomething(object o)
{
A aObject = o as A;
if (aObject != null)
{
aObject.DoSomething();
return;
}
B bObject = o as B;
if (bObject != null)
{
bObject.DoSomething();
return;
}
}
BUT 说实话,这真是太丑了......我真的会尝试重构接口。
答案 6 :(得分:0)
要么必须使用Zach和astander所示的接口(或Base类),要么在使用之前必须使用对象:
public void make_connection(Object x)
{
((A)x).connect() ;
// Do some more stuff...
x.disconnect() ;
return ;
}
答案 7 :(得分:0)
您也可以使用反射来调用方法
答案 8 :(得分:0)
您想要的是Duck Typing。
来自维基百科:
如其他人所说,C#4.0允许使用动态关键字Duck typing 是一种动态类型,其中对象的当前方法和属性集确定有效语义,而不是从特定类或特定接口的实现继承。