2种方法使用2种相同类型的泛型

时间:2010-07-23 10:43:48

标签: c# generics

如果我有以下课程:

class MyClass<T,U>
{
  public void DoSomething(T t)
  {
  }

  public void DoSomething(U u)
  {
  }
}

但是使用相同的类型构建它(new MyClass<int,int>()) 这编译很好,但是如果我试图调用DoSomething它会因为调用模糊而出错,这当然是正确的。但是如果通过反射或其他动态方式调用该方法会怎样。我想它会在运行时抛出一个异常。所以我的问题是为什么编译器允许我创建具有相同类型的类,如果有异常等待发生?

4 个答案:

答案 0 :(得分:4)

编译器关注实际的歧义,并没有突出显示与重载泛型方法相关的任何歧义。

如果您不想允许这样做,遗憾的是无法添加通用类型约束,即where T != U,因此您只需要在构造函数中抛出异常:

public MyClass()
{
    if (typeof(T) == typeof(U))
    {
       throw new Exception("T and U cannot be of the same type");
    }
}

您应该使用不同的名称,以便两个方法名称不会相互冲突。这是在这种情况下最安全的工作方式:

public DoSomethingWithFirst()
{
   // For T
}

public DoSomethingWithSecond()
{
   // For U
}

答案 1 :(得分:1)

那么,如果你不想打电话给DoSomething,那么能否让T和U成为同一类型是否有意义?如果是这样,编译器无缘无故地阻止它真的会感到愤怒吗?

事实上,如果你仔细选择了方法,那么可以用反射调用方法

我想说如果编译器应该做任何事情,它应该警告这个类本身的作者(不是类的用户),在某些情况下重载会导致歧义。坦率地说,过载可能会导致很多问题 - 在危险的情况下任何让人远离它的事情都会是一件好事:)

答案 2 :(得分:1)

你宁愿编译器没有允许这个吗?无限的情况很好,这个不是。

答案 3 :(得分:0)

顺便说一下,如果你不控制类,并且你想允许在MyClass<int, int>上调用这些方法,你可以在没有反射的情况下执行它,它将在运行时成功,没有异常。例如,如果您创建一个以TU作为参数的泛型方法,那么该方法中的重载解析可以区分它们:

public static class MyClassExtensions
{
    public static void DoSomethingT<T, U>(this MyClass<T, U> obj, T t)
    {
        obj.DoSomething(t);
    }

    public static void DoSomethingU<T, U>(this MyClass<T, U> obj, U u)
    {
        obj.DoSomething(u);
    }
}

DoSomethingT会选择DoSomething的超载T。这是在编译时选择的,对TU的所有值都有效。然后,您可以使用myObj.DoSomethingT(3)致电MyClass<int, int>,它会毫不含糊地调用MyClass.DoSomething(T t)

(正如其他人所说,如果你控制了这个类,那么你应该给这些方法赋予不同的名称。)