【问题标题】:Explain Generics in layman style in C#? [duplicate]在 C# 中以外行风格解释泛型? [复制]
【发布时间】:2009-11-02 23:29:46
【问题描述】:

What is the "< >" syntax within C# 的副本


实际上,我想知道“为什么以及何时应该使用泛型?”。

需要什么?

【问题讨论】:

  • 这真的值-2吗?我对此表示怀疑。 +1
  • “唯一愚蠢的问题是你没有问的问题”,我 +1。这是一个很好的基本问题。要让它成为“什么是 ”的副本,您必须已经知道答案。
  • @Jim :发布问题并没有错,但答案在欺骗帖子中,所以保持这个问题开放没有意义,是吗?
  • @Brann - 如果问题的措辞不同,那么我会说它应该保持开放。仅仅因为两个问题有相同的答案并不意味着它们是同一个问题。谷歌也将我引向了这个问题,而不是另一个。

标签: c# generics


【解决方案1】:

泛型是在 C# 中确保编译时类型安全的一种方式。

示例 - 预泛型:

class Person 
{
 string name;
 string lastname;
 public Person(string _name )  { this.name = _name; }
}

class ClientCode
{
   public static void Main()
   {
         //create a list of person
         ArrayList personList = new ArrayList();
         Person p1 = new Person("John");
         Person p2 = new Person("Ram");
         personList.Add(p1);
         personList.Add(p2);
         // BUT, someone can do something like:
         // ArrayList does not stop adding another type of object into it
         object q = new object();
         personList.Add(q);
         // while accessing personlist
         foreach(object obj in personlist)
         {
            Person p = obj as Person;
            // do something, for person
            // But it will fail for last item in list 'q' since its is not person.
         }
   }
}

示例-后泛型:

class ClientCode
{
   public static void Main()
   {
         //create a list of person
         List<Person> personList = new List<Person>();
         Person p1 = new Person("John");
         Person p2 = new Person("Ram");
         personList.Add(p1);
         personList.Add(p2);
         // Someone can not add any other object then Person into personlist
         object q = new object();
         personList.Add(q); // Compile Error.
         // while accessing personlist, No NEED for TYPE Casting
         foreach(Person obj in personlist)
         {
            // do something, for person
         }
   }
}

【讨论】:

    【解决方案2】:

    泛型可以让你在类型上参数化代码,就像参数让你在值上参数化它一样。这可能并不能解释很多,所以让我们一步一步来:

    假设您想要一个程序打印“我喜欢兔子”。你这样写:

    static void Main()
    {
        ILikeBunnies();
    }
    
    void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
    

    一切顺利。但你也喜欢奶酪,所以现在你有:

    static void Main()
    {
        ILikeBunnies();
        ILikeCheese();
    }
    
    void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
    void ILikeCheese()  { Console.WriteLine("I like cheese"); }
    

    您注意到您的两个功能几乎相同。您想重用 same 功能,但为您喜欢的内容提供不同的

    static void Main()
    {
        ILike("bunnies");
        ILike("cheese");
    }
    
    void ILike(string what) { Console.WriteLine("I like " + what); }
    

    这就是函数参数的用途:它们让您可以使用不同的值重用相同的代码。

    泛型就是这样,但不是传入不同的值,而是传入 types。假设您的代码需要将两个字符串捆绑到一个数组中:

    static void Main()
    {
        string[] s = Pair("a", "b");
    }
    
    string[] Pair(string a, string b) { return new string[] { a, b }; }
    

    很好,花花公子。后来你意识到你还需要将整数捆绑到一个数组中:

    static void Main()
    {
        string[] s = Pair("a", "b");
        int[]    i = Pair(1, 2);
    }
    
    string[] Pair(string a, string b) { return new string[] { a, b }; }
    int[]    Pair(int    a, int    b) { return new int[]    { a, b }; }
    

    就像以前一样,我们可以看到那里有一堆冗余。我们需要的是一个返回一对 whatever 的函数以及一个传入我们想要一对的类型的方法。这就是泛型的用途:

    static void Main()
    {
        string[] s = Pair<string>("a", "b");
        int[]    i = Pair<int>(1, 2);
    }
    
    T[] Pair<T>(T a, T b) { return new T[] { a, b }; }
    

    尖括号可以让你将类型传递给函数,就像括号让你传递值一样。这里的“T”是类型参数的名称,就像上面的值参数“what”一样。函数中出现的任何位置 T 都将替换为您传入的实际类型(示例中为 string 和 int)。

    除此之外,你可以用泛型做很多事情,但这是基本思想:泛型让你可以将类型传递给函数(和类),就像参数让你传递值一样。

    【讨论】:

    • 在你的最后一个例子中,T[] Triple... 应该是 T[] Pair( T a, T b ) { return new T[] { a, b }; }
    • 我知道这是旧的,但对于任何尝试使用它的人来说,他们需要声明通用方法静态:静态 T[] Pair(T a, T b) 等...或者它不会编译。
    【解决方案3】:

    泛型基本上消除了将对象转换为基本类型的需要。

    例如如果您想将一组 Foos 存储在列表中。

    您过去必须创建自己的 owen FooList 或将项目转换为对象。

    所有这些都需要你的时间和编译器。

    使用泛型,您所要做的就是坐在列表中,它会检查您的类型并加速您的程序。 (没有装箱和拆箱)

    【讨论】:

      【解决方案4】:

      假设你自己是一个算法,它可以对任何可以成对比较的对象(扑克牌、CD、名片等)进行排序。您实际上对这些具体对象提供的内容并不感兴趣,您可以比较它们。这样你就变成了一个泛型(这里的“泛型”是广义的,而不是 C# 意义上的)算法。

      .NET 中的泛型有助于促进这种特殊类型的行为,不仅在算法(泛型函数)方面,而且在泛型类型(类、结构、委托、接口)方面。

      【讨论】:

      • 我知道泛型是什么......这让我很困惑:(
      【解决方案5】:

      只是为了补充其他人会告诉你的内容,更实际地,尝试使用 ArrayListSystem.Array 对象执行某些操作,然后尝试使用 List&lt;T&gt; 执行此操作,您可以立即看到泛型如何让您写出更易读的代码,也写得更快。

      【讨论】:

        【解决方案6】:

        I blogged about it a long time ago, here。我正在使用 XML,我想要一个可以获取 XmlElement 或 XmlAttribute(基于 XPath)并让我使用它的助手。这是我在现实世界中完成的一个很好的简单示例,当时泛型对 C# 来说还很新。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-08
          • 2011-02-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多