给定以下层次结构:
class A
{
}
class B : A
{
public void Foo() { }
}
class C : A
{
public void Foo() { }
}
Run Code Online (Sandbox Code Playgroud)
这是第三方库,我无法修改它.有没有办法可以编写某种"通用模板化包装器",将Foo()方法转发给作为构造函数参数传递的适当对象?我最后编写了以下内容,它没有使用泛型,看起来相当难看:
class Wrapper
{
A a;
public Wrapper(A a)
{
this.a = a;
}
public void Foo()
{
if (a is B) { (a as B).Foo(); }
if (a is C) { (a as C).Foo(); }
}
}
Run Code Online (Sandbox Code Playgroud)
我喜欢一些模板约束Wrapper<T> where T : B or C.
das*_*ght 15
如果A没有Foo,你需要使用dynamic(参见Jon Skeet的回答)或使用lambdas和重载的小技巧:
class Wrapper {
private Action foo;
public Wrapper(B b) {
foo = () => b.Foo();
}
public Wrapper(C c) {
foo = () => c.Foo();
}
public void Foo() {
foo();
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以这样做:
var wb = new Wrapper(new B());
wb.Foo(); // Call B's Foo()
var wc = new Wrapper(new C());
wc.Foo(); // Call C's Foo()
Run Code Online (Sandbox Code Playgroud)
这将决定从Foo调用的那一刻到Wrapper创建的那一刻调用什么方法,这可能会节省一些CPU周期.
不,Foo就编译器而言,这两种方法完全不相关.在不知道开始使用的各个类型的情况下,最简单的方法是使用动态类型:
public void Foo()
{
dynamic d = a;
// Let's hope there's a suitable method at execution time!
d.Foo();
}
Run Code Online (Sandbox Code Playgroud)
据我所知,泛型不会帮助你.它不像是你可以约束的某个界面(至少没有你展示过的界面)T.
你也可以传入一个Action:
Wrapper wrapper = new Wrapper(b, b.Foo);
Run Code Online (Sandbox Code Playgroud)
这使得呼叫者稍微不方便,但非常一般......
| 归档时间: |
|
| 查看次数: |
12567 次 |
| 最近记录: |