任何人都可以举一个很好的例子来说明如何使用泛型类?

时间:2011-10-07 14:19:25

标签: c# class generics

我们最近了解了C#中的泛型类,但是我们的老师没有提到它们可以用于什么。我真的找不到任何好的例子,如果有人帮助我,我会非常高兴:)

你是否制作了自己的通用课程,以及你用它做了什么?

一些代码示例会让我和我的同学们真的很开心!原谅我的英语不好,我来自瑞典:)

快乐的编程!

抱歉 - 我想我可以写一下这个问题。我熟悉通用集合。我只是想知道你自己的泛型类可以用于什么。

感谢MSDN链接,在发布问题之前我确实已经阅读过了,但也许我错过了什么?我会再来一次!

11 个答案:

答案 0 :(得分:10)

通用收藏

集合的泛型非常有用,因为它们允许编译时类型安全。这有用的原因有几点:

  • 检索值时不需要强制转换。这不仅具有性能优势,而且还消除了运行时出现转换异常的风险

  • 当将值类型添加到非泛型列表(例如ArrayList)时,必须将值装箱。这意味着它们存储为引用类型。这也意味着不仅值被存储在内存中,而且对它的引用也是如此,因此使用了比necessery更多的内存。使用通用列表时会消除此问题。

通用课程

通用类可用于重用不同类型的公共代码。以一个简单的非通用工厂类为例:

public class CatFactory
{
  public Cat CreateCat()
  {
    return new Cat();
  }
}

我可以使用泛型类为(几乎)任何类型提供工厂:

public class Factory<T> where T : new()
{
  public T Create()
  {
    return new T();
  }
}

在这个例子中,我在类型参数T上放置了new()的泛型类型约束。这要求泛型类型包含一个无参数的构造函数,这使我能够在不知道类型的情况下创建实例。

答案 1 :(得分:6)

因为你说你是瑞典人,我想我会举一个整合宜家家具的例子。你的套装沙发是北美的一种感染,所以我想我会回馈一些东西:)想象一个代表一个特殊的椅子和桌子套件的课程。为了保持真实,我甚至会使用无意义的瑞典语言同音异义词:

// interface for included tools to build your furniture
public interface IToolKit {
    string[] GetTools();
}

// interface for included parts for your furniture    
public interface IParts {
    string[] GetParts();
}

// represents a generic base class for IKEA furniture kit
public abstract class IkeaKit<TContents> where TContents : IToolKit, IParts, new() {
    public abstract string Title {
        get;
    }

    public abstract string Colour {
        get;
    }

    public void GetInventory() {
        // generic constraint new() lets me do this
        var contents = new TContents();
        foreach (string tool in contents.GetTools()) {
            Console.WriteLine("Tool: {0}", tool);
        }
        foreach (string part in contents.GetParts()) {
            Console.WriteLine("Part: {0}", part);
        }
    }
}

// describes a chair
public class Chair : IToolKit, IParts {
    public string[] GetTools() {
        return new string[] { "Screwdriver", "Allen Key" };
    }

    public string[] GetParts() {
        return new string[] {
            "leg", "leg", "leg", "seat", "back", "bag of screws" };
    }
}

// describes a chair kit call "Fnood" which is cyan in colour.
public class Fnood : IkeaKit<Chair> {
    public override string Title {
        get { return "Fnood"; }
    }

    public override string Colour {
        get { return "Cyan"; }
    }
}

public class Snoolma : IkeaKit<Chair> {
    public override string Title {
        get { return "Snoolma "; }
    }

    public override string Colour {
        get { return "Orange"; }
    }
}

好的,现在我们已经掌握了如何构建一些廉价家具所需的所有内容:

var fnood = new Fnood();
fnood.GetInventory(); // print out tools and components for a fnood chair!

(是的,缺乏说明和椅子套件中的三条腿是故意的。)

希望这有助于以厚颜无耻的方式。

答案 2 :(得分:4)

如果有一个List对象(非泛型),可以将任何可以转换为Object的东西存储到其中,但是在编译时无法知道从中获取什么类型的东西。相比之下,如果一个人拥有一个通用List&lt; Animal&gt;,那么人们可以存储的唯一东西就是Animal或其衍生物,并且编译器可以知道将从中拉出的唯一东西将是Animal。因此,编译器可以将事物从List中拉出并直接存储到Animal类型的字段中,而无需进行运行时类型检查。

此外,如果泛型类的泛型类型参数恰好是值类型,则使用泛型类型可以消除对与Object进行强制转换的需要,这是一个名为“Boxing”的过程,它将值类型实体转换为引用 - 对象;拳击有点慢,有时可以改变值类型对象的语义,因此最好尽可能避免。

请注意,即使SomeDerivedClass类型的对象可以替代TheBaseClass,通常也可以使用GenericSomething&lt; SomeDerivedClass&gt;不能替代GenericSomething&lt; TheBaseClass&gt;。问题是如果可以替代例如列表&lt;长颈鹿&gt;对于List&lt; Zebra&gt;,可以传递List&lt; Zebra&gt;一个期望采取List&lt; Giraffe&gt;的例程并将大象存放在其中。但有几种情况允许可替代性:

  1. 派生类型的数组可以传递给期望基类型数组的例程,前提是这些例程不会尝试将任何不属于正确派生类型的项存储到这些数组中。
  2. 接口可以声明为具有“out”类型参数,如果这些接口唯一要做的就是返回(“输出”)该类型的值。长颈鹿供应商可能会取代动物供应商,因为它所要做的就是供应长颈鹿,长颈鹿又可以替代动物。这些接口相对于那些参数是“协变的”。

此外,如果接口所做的唯一事情是按值接受该类型的参数,则可以声明接口以声明“in”类型参数。动物食者可能会取代长颈鹿食者,因为 - 能够食用所有动物,因此能够吃掉所有长颈鹿。这些接口相对于那些参数是“逆变的”。

答案 3 :(得分:2)

最常见的例子是List,Dictionary等集合。所有这些标准类都是使用泛型实现的。

另一个用途是为诸如排序和比较之类的操作编写更多通用实用程序类或方法。

答案 4 :(得分:1)

嗯,你在框架内有很多样本。想象一下,你需要实现一个整数列表,然后是一个字符串列表...以及后来的客户类列表...等等。这将是非常痛苦的。

但是,如果你实现了一个通用列表,问题就会在更短的时间内得到解决,代码更少,你只需要测试一个类。

也许有一天,您需要实现自己的队列,并提供有关每个元素优先级的规则。然后,如果可能的话,将此队列设为通用是个好主意。

这是一个非常简单的示例,但随着您提高编码技能,您将看到(例如)通用存储库(它是设计模式)的有用性。

不是每天的程序员都会制作通用课程,但是相信我,你会很乐意在需要的时候使用这样的工具。

答案 5 :(得分:1)

以下是一篇可以提供帮助的Microsoft文章:http://msdn.microsoft.com/en-us/library/b5bx6xee%28v=vs.80%29.aspx

正如@Charlie所提到的,我看到的最大的好处是泛型的编译时安全性。我还使用了一个泛型类来实现DataReader,以便批量插入到数据库中。

答案 6 :(得分:1)

仿制药的现实世界示例。

认为你有一个笼子里面有许多不同的鸟类(鹦鹉,pegion,麻雀,乌鸦,鸭子)(非通用)。

现在你被分配了一项工作,将鸟从上面指定的笼子移到单独的笼子里(专门为单只鸟建造)。

(非通用列表存在问题) 从旧笼子中抓出特定的鸟并将它移到为它制作的笼子里是一项繁琐的工作。(哪种类型的鸟笼 - c#中的类型铸造)

通用列表

现在想想你有一个单独的鸟笼,你想要转移到为其制作的其他笼子。这将是一项简单的任务,你不需要花时间去做(不需要任何类型的铸造 - 我的意思是用笼子绘制鸟类)。

答案 7 :(得分:0)

微软看一下这篇文章。您可以清楚地了解如何使用它们以及何时使用它们。 http://msdn.microsoft.com/en-us/library/ms172192.aspx

答案 8 :(得分:0)

各种通用集合是泛型使用的最佳示例,但如果您想要一个自己可以生成的示例,您可以查看我对这个旧问题的回答:

uses of delegates in c or other languages

不确定它是否是使用仿制药的一个特别好的例子,但这是我偶尔会做的事情。

答案 9 :(得分:0)

您在谈论基类(或者可能是抽象类)吗?作为一个类,您将构建其他类(子类)?

如果是这种情况,那么您将创建一个基类来包含对继承它的类通用的方法和属性。例如,汽车类将包括轮子,引擎,门等。那么也许你可能会创建一个继承汽车类的sportsCar子类并添加诸如扰流板,turboCharger等属性。

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programmingenter link description here

如果没有某些背景,很难理解“泛类”的含义。

答案 10 :(得分:0)

我的朋友不是程序员,我想解释什么是泛型?我将在下面解释他的泛型。因此,这是使用泛型的真实情况。

“在隔壁的街道上有这个制造商。他可以制造任何汽车。但是有时他只能制造一种汽车。上周,他为我制造了一辆汽车,这周,他为我制造了卡车。叔叔,就像我说的那样,这个制造单位是如此通用,可以制造客户指定的东西,但是请注意,当您与该制造商联系时,必须使用所需的汽车,否则就无法接近他。 “