是否有可能使C#使用最特定类型而不是基本类型的方法重载? [英] Is it possible to get c# to use method overload of most specific type rather than base type?

查看:59
本文介绍了是否有可能使C#使用最特定类型而不是基本类型的方法重载?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果您的方法重载了派生类型,则在运行时调用的方法取决于变量的类型,即使基础对象实际上是派生类型也是如此:

If you have a method which is overloaded with a derived type, the method called at run-time depends on the type of your variable, even if the underlying object is actually of the derived type:

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

我想找到一种改变这种行为的方法,以便为给定参数调用最具体的方法.

I would like to find a way to alter this behaviour such that the most specific method invoked for a given parameter.

所需的输出:

FOO
FOOBAR
FOOBAR  // because theDerivedObject is an instance of DerivedClass 

这将允许对一堆物品进行特定处理,所有物品都是从一个基础派生的.

This would allow specific processing for a bunch of items, all derived from a base.

这在c#中可行吗?

说明-实际上,不会进行明确的强制类型转换,因为这些项目可能会出现在混合类型的集合列表中:

A clarification - in practice there would be no explicit cast, as the items would likely be in a list of collection of mixed types:

使用没有显式强制转换的列表的示例:

Example using a list without an explicit cast:

    foreach (BaseClass item in new []{ theBaseObject, theDerivedObject })
    {
        Console.WriteLine(processor.Compose(item));
    }

实际输出:

FOO
FOO

所需的输出:

FOO
FOOBAR

很明显,转换仍在进行-但删除它并不容易.

Obviously the cast is still happening - but it's not easy to remove it.

推荐答案

此代码使我想起了 黑线鳕的眼睛 诗:

This code reminds me of the Haddocks' Eyes poem:

但是我在考虑一个计划
 将晶须染成绿色,
并始终使用这么大的风扇
 无法看到它们.

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).

First, your code creates a subclass, but then it casts the object back to the base class, so the compiler cannot see the actual type! The overload in your example is resolved at compile time, so the Compose(BaseClass item) will be called.

您可以解决所有问题,并让.NET通过隐藏所有重载并公开一个采用基类并执行动态强制转换的方法来为您动态解决重载:

You could turn things around and have .NET resolve the overload dynamically for you by hiding all overloads, and exposing a single method that takes a base class and performs a dynamic cast:

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,这告诉系统必须根据BaseClass对象的运行时类型选择ComposeImpl的实际重载.

the item is cast to dynamic, which tells the system that the actual overload of ComposeImpl must be picked based on the run-time type of the BaseClass object.

这篇关于是否有可能使C#使用最特定类型而不是基本类型的方法重载?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆