and*_*ecu 7 c# generics overloading
我有以下场景:
class Foo { }
class Foo<T> : Foo { }
Run Code Online (Sandbox Code Playgroud)
然后是两种方法
void DoStuff(Foo foo) 
{
     DoStuffImpl(foo);
}
void DoStuffImpl(Foo foo) 
{ 
     Console.WriteLine("A");
}    
void DoStuffImpl<T>(Foo<T> foo) 
{ 
     Console.WriteLine("B");
} 
void Main() 
{
     DoStuff(new Foo<int>()); // prints A
}
Run Code Online (Sandbox Code Playgroud)
(注意,代码是在浏览器中编写的,但描述了我面临的情况)
如何让它调用泛型方法,然后打印B?
这可以在没有反思的情况下完成吗?关于如何用反射完成,我有一些想法,但我正在寻找一个更清洁的解决方案,如果存在的话.
注意:我不能创建DoStuff泛型,因为这将与WCF一起使用,并且不允许打开泛型类型.
Jon*_*eet 17
(我假设你已经理解为什么会发生这种情况.如果没有,请阅读我的重载决议文章并告诉我它是否仍然不清楚.)
如果您使用的是C#4,则可以使用动态类型:
void DoStuff(Foo foo) 
{
    dynamic d = foo;
    DoStuffImpl(d);
}
Run Code Online (Sandbox Code Playgroud)
注意这不仅仅有一个动态参数 - 这个想法是通过限制foo为类型Foo或子类,我们总是有一个有效DoStuffImpl的调用...它只是在执行时确定最佳方法,而不是编译时间.
如果你被困在C#4之前,你可以通过双重调度来实现:
class Foo
{
    public virtual void CallStuffImpl(FooImplType x)
    {
        x.DoStuffImpl(this);
    }
}
class Foo<T> : Foo
{
    public override void CallStuffImpl(FooImplType x)
    {
        // Looks like it's redundant, but isn't! "this" is
        // known to be Foo<T> rather than Foo
        x.DoStuffImpl(this);
    }
}
Run Code Online (Sandbox Code Playgroud)
然后:
void DoStuff(Foo foo) 
{
    foo.CallStuffImpl(this); // Let it dispatch appropriately
}
Run Code Online (Sandbox Code Playgroud)
        Eri*_*ert 17
过载分辨率在编译时执行.编译"DoStuff"时,它已经决定调用哪个版本的DoStuffImpl,它根据编译时可用的信息决定,而不是运行时可用的信息.
C#中有四种方法调度:
静态调度在编译时选择静态方法.在运行时,调用所选方法.
实例调度在编译时选择实例方法.在运行时,调用所选方法.(这是在非虚拟实例方法和使用"base"调用的虚拟方法上使用的调度形式.)
虚拟调度在编译时选择实例方法.在运行时,将调用该对象的运行时类型上该方法的最重写版本.
动态调度在编译时不执行任何操作(*).在运行时,编译器再次启动并在运行时进行编译时分析,并生成新的新代码,如果您在编译时首先将其编写完成,那么这些代码将会被编写. 这听起来有点贵; 幸运的是,结果被缓存,因此在第二次调用时,您不会再次获得所有分析和代码的成本.
动态调度仅适用于C#4或任何版本的VB.
(*)这不是真的; 在某些情况下,即使方法的参数是动态的,编译器也可以在编译时进行分析.细节很复杂.
|   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           2279 次  |  
        
|   最近记录:  |