将泛型参数传递给重载方法

时间:2015-05-14 19:58:06

标签: c#

是否可以将泛型参数传递给重载方法?

class Shop
{
  void CreateButton<T>(T itemToBuy)
  {
    var button = CreateButtonImpl();
    button.onClick.AddListener(() => Buy(itemToBuy));
  }

  void Buy(C c) {}
  void Buy(D d) {}
}

class C {}
class D {}

在上面的代码中,有一个错误,T无法转换为C.有什么方法可以修复它吗?

3 个答案:

答案 0 :(得分:1)

该方法首先不应该是通用的,因为它只能支持两种特定类型,而不是任何类型(在一般意义上它实际上是泛型

只有Caller的两个重载,一个接受C,另一个接受D

无法以允许静态类型检查的方式解决此问题。如果您确实必须这样做,那么您可以做的最好的事情是检查参数的类型(即通过is)并直接调用每个重载。你可以让编译器使用dynamic为你编写代码,但是你仍然会失去所有的静态类型安全性,并且会受到相当显着的性能影响。

答案 1 :(得分:1)

不,这是不可能的。从调用方那里你可能知道你传入了什么(虽然如果你传递一个基类你也可能不一样),但是从内部你知道的是T以及你对它的任何限制(没有在这种情况下)。

要执行您想要的操作,您需要获取TT.GetType())的运行时类型,并将其与其他类的类型进行比较(typeof(C)和{{分别执行1}},然后执行转换并手动将参数转发到右侧函数。

答案 2 :(得分:0)

我无法在不访问CreateButtonImpl方法的情况下测试代码,但我认为如果将泛型类型声明推送到类级别(远离方法级别),请删除其中一种buy方法,并用接受类型为T的参数替换另一个,您将得到您想要的。这是一个示例:

namespace EmptyConsole
{

    class Shop<T>
    {

        public void CreateButton(T itemToBuy)
        {
            var button = CreateButtonImpl();
            button.onClick.AddListener(() => Buy(itemToBuy));
        }

        void Buy(T itemToBuy) { }
    }

    class C { }
    class D { }

    class Program
    {
        static void Main(string[] args)
        {
            var shop = new Shop<C>();
            shop.CreateButton(new C());
        }
    }
}

将C和D类实现相同的接口(创建表示它们可以执行的操作的新接口)并将泛型类型参数T限制为实现该共享接口的东西也是值得的。这是一个修改过的示例,显示了该场景的样子:

namespace EmptyConsole
{

    class Shop<T> where T : IPurchaseable
    {

        public void CreateButton(T itemToBuy)
        {
            var button = CreateButtonImpl();
            button.onClick.AddListener(() => Buy(itemToBuy));
        }

        void Buy(T itemToBuy) { }
    }

    interface IPurchaseable { }

    class C : IPurchaseable { }
    class D : IPurchaseable { }

    class Program
    {
        static void Main(string[] args)
        {
            var shop = new Shop<C>();
            shop.CreateButton(new C());
        }
    }
}