【发布时间】:2015-08-27 12:55:14
【问题描述】:
在我陈述我的问题之前,让我提供一些关于我正在尝试做的事情的背景信息,因为也许有更好的方法来实现它。
我有一个类C,它继承了两个接口A 和B。
public interface A
{
void DoStuff();
}
public interface B
{
void DoStuff();
}
C 为DoStuff 实现了两个不同的主体。
void A.DoStuff()
{
Console.WriteLine("A");
}
void B.DoStuff()
{
Console.WriteLine("B");
}
我当然知道DoStuff 可以像下面这样调用。
var c = new C();
var a = (A)c;
a.DoStuff();
var b = (B)c;
b.DoStuff();
我想要做的是避免将C 转换为A 或B,然后在A 或B 上调用DoStuff。
所以我认为我可以实现一个通用方法来为我做这件事,所以我首先尝试这样。
public void DoStuff<T>()
{
var i = (T)this;
i.DoStuff();
}
当然,考虑到您可以将this 转换为T,这将导致编译器错误,因此我的下一步是尝试创建一个传递this 实例的静态方法,然后在那里进行了转换。
private static To ConvertToDoStuffInterface<From, To>(From from)
{
return (To)from;
}
我没想到它会起作用,但值得一试。正如我所料,它会导致编译器错误,因为From 无法显式转换为To。
我最后的手段是使用dynamic 关键字,当然它顺利通过ConvertToDoStuffInterface,但是一旦我尝试调用DoStuff,它就会抛出一个RuntimeBinderException,我有点怀疑它可能会。我知道为什么会抛出异常,这当然是因为它无法将ConvertToDoStuffInterface 的结果正确绑定到任何类型,并且我认为需要进行某种类型的转换。
这是dynamic 用法的代码。
private static dynamic ConvertToDoStuffInterface<T>(dynamic from)
{
return (T)from;
}
public void DoStuff<T>()
{
var i = ConvertToDoStuffInterface<T>(this);
i.DoStuff();
}
我的问题是,如果没有更好的方法可以使用泛型或dynamic 来实现这一点,我将如何进行从dynamic 到T 的转换?有没有一种方法可以检查传递给DoStuff<T> 的类型是否具有DoStuff 方法,然后允许我最初尝试的方法?
为了澄清我想要做的事情是这样的
var c = new C();
c.DoStuff<A>(); // Calls A.DoStuff()
c.DoStuff<B>(); // Calls B.DoStuff()
这是我的C 实现。
public class C : A, B
{
public void DoStuff<T>()
{
// ... DoStuff<T> implementation here ...
}
void A.DoStuff()
{
Console.WriteLine("A");
}
void B.DoStuff()
{
Console.WriteLine("B");
}
}
【问题讨论】:
-
@DavidE 这是一个不好的做法。您永远不应该在
as关键字之后尊重实例。它可能为空。您需要在那里进行空检查。更干净的方法是使用直接投射。 -
我不明白
c.DoStuff<A>怎么比((A)c).DoStuff干净。在这两种情况下,您都必须指定要调度的接口。 -
确实,感谢您指出 Sriram! (为将来的读者提供上下文 - 我删除了之前建议
(A as C).DoStuff()的评论,建议不好) -
虽然这是真的李,但这样做的目的并不是真正的可读性。
标签: c# generics dynamic explicit-interface