如果你有一个用派生类型重载的方法,在运行时调用的方法取决于你的变量的类型,即使底层对象实际上是派生类型:
class Program
{
static void Main(string[] args)
{
BaseClass theBaseObject = new BaseClass
{
Foo = "FOO"
};
DerivedClass theDerivedObject = new DerivedClass
{
Foo = "FOO",
Bar = "BAR"
};
Processor processor = new Processor();
Console.WriteLine(processor.Compose(theBaseObject));
Console.WriteLine(processor.Compose(theDerivedObject));
Console.WriteLine(processor.Compose((BaseClass) theDerivedObject));
}
}
public class Processor
{
public string Compose(BaseClass item)
{
return item.Foo;
}
public string Compose(DerivedClass item)
{
return Compose((BaseClass)item) + item.Bar;
}
}
public class BaseClass
{
public string Foo { get; set; }
}
public class DerivedClass : BaseClass
{
public string Bar { get; set; }
}
实际输出:
FOO
FOOBAR
FOO
我想找到一种方法来改变这种行为,以便为给定参数调用最具体的方法。
期望的输出:
FOO
FOOBAR
FOOBAR // because theDerivedObject is an instance of DerivedClass
这将允许对一堆项目进行特定处理,所有项目都来自一个基础。
这在 C# 中可行吗?
编辑:
澄清 - 实际上不会有显式转换,因为项目很可能在混合类型集合的列表中:
使用没有显式转换的列表的示例:
foreach (BaseClass item in new []{ theBaseObject, theDerivedObject })
{
Console.WriteLine(processor.Compose(item));
}
实际输出:
FOO
FOO
期望的输出:
FOO
FOOBAR
显然类型转换仍在发生 - 但要删除它并不容易。
最佳答案
这段代码让我想起了 Haddocks' Eyes诗:
But I was thinking of a plan
To dye one's whiskers green,
And always use so large a fan
That they could not be seen.
首先,您的代码创建了一个子类,然后将对象强制转换回基类,因此编译器看不到实际类型!您的示例中的重载在编译时得到解决,因此 Compose(BaseClass item)
将被调用。
您可以扭转局面,让 .NET 为您动态解析重载,方法是隐藏所有重载,并公开采用基类并执行动态转换的单个方法:
public class Processor {
public string Compose(BaseClass item) {
return ComposeImpl((dynamic)item);
}
private string ComposeImpl(BaseClass item) {
return item.Foo;
}
private string ComposeImpl(DerivedClass item) {
return ComposeImpl((BaseClass)item) + item.Bar;
}
}
“魔法”就在这条线上:
return ComposeImpl((dynamic)item);
item
被转换为 dynamic
,它告诉系统必须根据运行时选择 ComposeImpl
的实际重载BaseClass
对象的类型。
关于c# - 是否有可能让 c# 使用大多数特定类型而不是基类型的方法重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35770767/