代码之家  ›  专栏  ›  技术社区  ›  Joel Coehoorn

约束到接口的泛型参数和仅使用接口之间的区别

  •  12
  • Joel Coehoorn  · 技术社区  · 17 年前

    这两者之间有什么区别:

    void MyMethod(IMyInterface value)
    {
        //...
    }
    

    这个:

    void MyMethod<T>(T value) where T : IMyInterface
    {
        //...
    }
    
    7 回复  |  直到 17 年前
        1
  •  11
  •   JaredPar    17 年前

    在非泛型的情况下,您无法保证对对象底层类型的访问。大多数类型的你可以抓住价值。GetType(),但用户可以传递Null并阻止您。

        2
  •  7
  •   Marc Gravell    17 年前

    贾里德提到了其中的一些观点;另一个有趣的问题是:使用泛型,可以避免值类型的装箱 只要 struct Foo : IMyInterface 把它递进去,它就不会被装箱了。

    这种差异在收藏等方面变得更加明显:

    static void Foo(IEnumerable<IMyInterface> data) {}
    

    兽医

    static void Foo<T>(IEnumerable<T> data) 
        where T : IMyInterface {}
    

    现在,由于C#3.0没有协方差(数组除外),我无法传递 List<Bar> 到顶部,即使 Bar : IMyInterface -但我可以用第二个(隐含 T = Bar ).

        3
  •  3
  •   Mehrdad Afshari    17 年前

    但说真的,虽然它们看起来很相似,但它们之间存在根本差异。一个区别是,在运行时,JIT编译器将为将用于泛型版本的每种值类型生成代码。非泛型版本需要将值类型装箱,以便传递给函数。

    在与代表打交道时,这种差异也很重要。签名 MyMethod<int> 火柴 void MyDelegate(int x) 而非通用版本不匹配。

        4
  •  3
  •   Frank Krueger    17 年前

    多个 对象必须实现的接口:

    class Dictionary<TKey,TVal>
        where TKey: IComparable, IEnumerable
        where TVal: IValue
    { ... }
    
        5
  •  1
  •   xanatos    12 年前

    另一个微妙的区别是,你不能只在约束上重载方法(约束不是方法签名的一部分):

    这是非法的:

    void MyMethod<T>(T value) where T : IMyInterface
    {
        //...
    }
    
    void MyMethod<T>(T value) where T : IMyInterface2
    {
        //...
    }
    

    虽然这是合法的:

    void MyMethod(IMyInterface value)
    {
        //...
    }
    
    void MyMethod(IMyInterface2 value)
    {
        //...
    }
    
        6
  •  0
  •   TheHolyTerrah    17 年前

    在这种情况下需要考虑的另一个警告是,在泛型中使用“where T:<%your base interface or abstraction%>”可能会过度使用,从而使泛型类型在本质上非泛型。

    IE:请记住,通过将泛型方法隔离到IMyInterface,您将该方法隔离到仅实现IMyInterfaces的类型。因此,如果你只是选择基于良好的面向对象编程原则使用IMyInterface,但你在任何地方都只有一个(或在某些情况下只有极少数)潜在类型可以实现该接口,那么你就没有达到使用泛型的目的。在这种情况下,第一种选择会更好。

        7
  •  0
  •   supercat    12 年前

    一般来说,泛型方法的另一个区别(尽管不是你的例子)是,如果有一个方法像 T MungeThing<T>(T it) where T:IMungeable<T> 和类 Fnord 实现 IMungeable<Fnord> ,则代码将能够说: Fnord thing1, thing2; ... thing1 = MungeThing(thing2); MungeThing 将返回a Fnord 而不是任意实施 IMungable .