关于C#泛型的最重要的事情......经验教训

时间:2009-02-28 21:25:43

标签: c# .net generics

您对泛型有哪些最重要的知识:隐藏的功能,常见的错误,最佳和最实用的做法,提示......

我开始使用泛型实现我的大部分库/ API,并希望收集在实践中发现的最常见的模式,提示等。

让我正式提出一个问题:你对仿制药最重要的是什么?

请尝试提供示例 - 与理解和过于干燥的描述相比,它更容易理解

由于

这个问题有点类似于Jon's question,但是在另一个主题上。

11 个答案:

答案 0 :(得分:14)

我学到的最重要的事情之一是你可以constrain the generic type parameter(s)。这可能非常强大,允许您仅为特定类型的对象定制类,并允许您在泛型类中使用该类型的成员。我意识到这是非常基础的,但它是让泛型非常有用的东西之一。

答案 1 :(得分:4)

当涉及到静态成员之类的东西时,泛型类型的每个特化都被视为唯一类型。例如,使用此类型:

class GenericType<T>
{
    public static int SomeValue;
}

如果我们这样做,断言就会成功:

GenericType<int>.SomeValue = 3;
Debug.Assert(GenericType<double>.SomeValue == 0);

这是因为:

typeof(GenericType<int>) != typeof(GenericType<double>)

即使

typeof(GenericType<int>.GetGenericTypeDefinition() == typeof(GenericType<double>).GetGenericTypeDefinition()

答案 2 :(得分:3)

了解C#中泛型类型推断的功能和局限性。深入理解编译器可以,不能根据(例如)方法中的参数类型推断出什么,可以使您的API的常见用例更具可读性。

答案 3 :(得分:3)

我学到的关于仿制药的最重要的一课是:你使用它们越多越好。

答案 4 :(得分:2)

没有协方差或反差(至少在3.5中)。在设计包含泛型类型参数的类层次结构时要注意这一点。

答案 5 :(得分:2)

两个有趣的课程。第一;列表;试着用T来思考; for full details see here,但简而言之,您需要使用:

public void Foo<T>(IList<T> data) where T : SomeBaseClassOrInterface {}

而不是:

public void Foo(IList<SomeBaseClassOrInterface> data) {}

第二:watch for the edge cases ;-p

你能在这里看到陷阱吗?

static void Foo<T>() where T : new()
{
    T t = new T();
    Console.WriteLine(t.ToString()); // works fine
    Console.WriteLine(t.GetHashCode()); // works fine
    Console.WriteLine(t.Equals(t)); // works fine

    // so it looks like an object and smells like an object...

    // but this throws a NullReferenceException...
    Console.WriteLine(t.GetType()); // BOOM!!!
}

答案 6 :(得分:1)

不知道它们是否最重要,但我学会了以下内容:

如果您不知道frikkin类型,泛型将只能通过反射进行实例化。在某些情况下,您可能需要非泛型接口才能在类型未知的情况下使用泛型类。

我几乎破坏了我的头,直到我嘲笑那个

public class Foo<T> where T : Foo<T> {
  public T CloneMe() ...
}

是完全有效的代码,允许您的基类公开与专用类相关的方法和属性......最终在状态机的状态定义中结束:

public abstract class Machine<S,M> where S : State<S,M> where M : Machine<S,M>  {
    protected S state;
}

public abstract class State<S,M> where S : State<S,M> where M : Machine<S,M> {
    protected M machine;
}

泛型可能会变得有点笨拙。前几天我有这个:

List<Tuple<Expression<Func<DataTable,object>>,Expression<Func<DataTable,object>>>>

...呼

答案 7 :(得分:1)

MyGeneric<T> where T : IComparable

没有

MyGeneric<IComparable> 

它的基类。

答案 8 :(得分:1)

我已经了解到泛型是一种非常强大的工具,但滥用会导致代码无法读取。

答案 9 :(得分:0)

首先,了解Generics在C#中的工作方式非常重要。这个article为Anders Hejlsberg(c#之父)提供了一个很好的泛型概述。我不认为尽可能经常使用它们就是那么好。在真正有意义的时候使用泛型。永远记住极限编程中的KISS和YAGNI(保持简单愚蠢;你不需要它)。

答案 10 :(得分:0)

通用委托类型始终是类型不变的。

我遇到了类似于前几天链接中概述的问题,这引起了一些混乱,因为我不明白我为什么要投射我的收藏。

http://www.theserverside.net/blogs/thread.tss?thread_id=47323