我对C#很新,我无法理解项目中类的行为。
我使用的接口定义了一个带有类型约束的泛型,这是另一个接口。
当我调用泛型时,我知道参数上存在某个方法(因为类型约束),但是当我调用它时,这个方法不会被执行。
到目前为止,我唯一的解决方法是将方法调用包含在特定于类型的方法重载中。
使用具有等效类型结构的以下代码段可以更好地解释这一点:
public interface ITrickable
{
void GetRabbitOut();
}
public interface IMagic
{
void DoTricks<T>(T obj) where T : ITrickable;
}
public class Hat : ITrickable
{
public void LiftUp() { Console.WriteLine("Lifting up the hat..."); }
public void GetRabbitOut() { Console.WriteLine("A rabbit came out the hat !"); }
}
public class Box : ITrickable
{
public void OpenDoubleBottom() { Console.WriteLine("Opening the box..."); }
public void GetRabbitOut() { Console.WriteLine("A rabbit came out the box !"); }
}
public abstract class Magician : IMagic
{
public abstract void DoTricks<T>(T obj) where T : ITrickable;
}
现在,如果我使用以下课程致电DoTricks(new Hat()); DoTricks(new Box());
:
public class Houdini : Magician
{
public override void DoTricks<T>(T obj)
{
try {
DoTricks(obj); }
catch {
throw new NotImplementedException(); }
}
public void DoTricks(Hat obj)
{
obj.LiftUp();
obj.GetRabbitOut();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
obj.GetRabbitOut();
}
}
输出符合预期:
Lifting up the hat...
A rabbit came out the hat !
Opening the box...
A rabbit came out the box !
但是如果这个类定义如下:
public class Genesta : Magician
{
public override void DoTricks<T>(T obj)
{
try {
DoTricks(obj);
obj.GetRabbitOut(); } // <--- This seems to be ignored !?
catch {
throw new NotImplementedException(); }
}
public void DoTricks(Hat obj)
{
obj.LiftUp();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
}
}
输出
Lifting up the hat...
Opening the box...
问题是为什么在{2}中没有调用GetRabbitOut
?
编辑:主叫代码为:
public static void Main(string[] args)
{
var houdini = new Houdini();
var hat = new Hat();
var box = new Box();
houdini.DoTricks(hat);
houdini.DoTricks(box);
Console.ReadLine();
}
答案 0 :(得分:1)
注意你的方法调用(我想它看起来像这样):
Genesta g = new Genesta();
g.DoTricks(new Hat());
g.DoTricks(new Box());
由于您调用g.DoTricks(new Hat())
而不是g.DoTricks<Hat>(new Hat())
,因此调用Genesta类的确切方法为DoTricks(T obj)
而非DoTricks<T>(T obj)
并不令人惊讶。在考虑DoTricks(T obj)
...
public void DoTricks(Hat obj)
{
obj.LiftUp();
}
public void DoTricks(Box obj)
{
obj.OpenDoubleBottom();
}
结果实际上是您对这些方法的期望!
但是,如果您要调用这样的通用方法......
g.DoTricks<Hat>(new Hat());
您将陷入无限递归,因为该方法会无限期地调用自身。 DoTricks<T>(T obj)
将始终调用自身,而不是专门的重载DoTricks(Hat)
或DoTricks(Box)
之一,因为编译器在运行时之前无法知道T实际上是Hat或Box。
顺便说一句,Houdini类经历了同样的效果 - 恰好它的特定DoTricks(Hat)
和DoTricks(Box)
方法会产生您通过调用DoTricks<T>(T obj)
所期望的结果。