任何人都可以举一个很好的例子来说明通用类的用途吗?

发布于 2024-12-08 19:48:13 字数 276 浏览 1 评论 0原文

我们最近学习了 C# 中的泛型类,但我们的老师没有提及它们的用途。我真的找不到任何好的例子,如果有人帮助我,我会非常高兴:)

你创建了自己的通用类吗?你用它做什么?

一些代码示例会让我和我的同学们非常高兴!请原谅我的英语不好,我来自瑞典:)祝你

编程愉快!

抱歉 - 我想我可以把问题写得更好一点。我熟悉通用集合。我只是想知道你自己的通用类可以用来做什么。

感谢您提供的 MSDN 链接,我在发布问题之前确实阅读了它们,但也许我错过了一些东西?我会再看一遍!

We recently learned about generic classes in C#, but our teacher failed to mention what they can be used for. I can't really find any good examples and would be extremly happy if somebody help me out :)

Have you made your own generic class, and what did you use it for?

Some code examples would make me, and my classmates, really happy! Pardon the bad english, I am from sweden :)

happy programming!

Sorry- I think I could have written the question a bit better. I am familar with generic collections. I just wondered what your own generic classes can be used for.

and thank you for the MSDN links, I did read them before posting the question, but maybe I missed something? I will have a second look!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

宣告ˉ结束 2024-12-15 19:48:13

泛型集合

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

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

  • 当将值类型添加到非泛型列表(例如 ArrayList)时,必须对值进行装箱。这意味着它们存储为引用类型。这还意味着不仅该值会存储在内存中,而且对其的引用也会存储在内存中,因此使用了超出必要的内存。使用泛型列表时可以消除此问题。

泛型类

泛型类对于重用不同类型的通用代码非常有用。以一个简单的非泛型工厂类为例:

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

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

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

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

Generic Collections

Generics for collections are very useful because they allow compile time type safety. This is useful for a few reasons:

  • No casting is required when retreiving values. This is not only a performance benefit but also eliminates the risk of there being a casting exception at runtime

  • When value types are added to a non generic list such as an ArrayList, the value's have to be boxed. This means that they are stored as reference types. It also means that not only does the value get stored in memory, but so does a reference to it, so more memory than necessery is used. This problem is eliminated when using generic lists.

Generic Classes

Generic classes can be useful for reusing common code for different types. Take for example a simple non generic factory class:

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

I can use a generic class to provide a factory for (almost) any type:

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

In this example I have placed a generic type constraint of new() on the type paramter T. This requires the generic type to contain a parameterless contructor which enables me to create an instance without knowing the type.

清醇 2024-12-15 19:48:13

就因为你说你是瑞典人,我想我应该举一个整合宜家家具的例子。你的套件沙发在北美很流行,所以我想我应该回馈一些东西:)想象一下一个类,它代表了用于构建椅子和桌子的特定套件。为了保持真实性,我什至会使用无意义的瑞典语同音异义词:

// 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!

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

希望这能厚颜无耻地有所帮助。

Just because you said you are Swedish, I thought I'd give an example integrating IKEA furniture. Your kit couches are an infestation in north america, so I thought I'd give something back :) Imagine a class which represents a particular kit for building chairs and tables. To remain authentic, I'll even use nonsense swedish linguistic homonyms:

// 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"; }
    }
}

Ok, so now we've got all the bits we need to figure out how to build some cheap furniture:

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

(Yes, the lack of instructions and the three legs in the chair kit is deliberate.)

Hope this helps in a cheeky way.

恰似旧人归 2024-12-15 19:48:13

如果有一个 List 对象(非泛型),则可以将任何可以转换为 Object 的内容存储到其中,但无法在编译时知道从中得到什么类型的内容。相比之下,如果有一个通用列表,则可以存储到其中的唯一事物是Animal或其派生类,并且编译器可以知道将从其中取出的唯一事物将是Animal。因此,编译器可以允许将内容从 List 中取出并直接存储到 Animal 类型的字段中,而不需要运行时类型检查。

此外,如果泛型类的泛型类型参数恰好是值类型,则使用泛型类型可以消除在 Object 之间进行转换的需要,这一过程称为“装箱”,它将值类型实体转换为引用类型对象;装箱有点慢,有时会改变值类型对象的语义,因此最好尽可能避免。

请注意,尽管 SomeDerivedClass 类型的对象可以替代 TheBaseClass,但一般来说,GenericSomething是可用的。不能替代 GenericSomething。问题是,如果可以用例如 List来替代。对于 List,可以传递 List。到一个期望将 List的例程并在里面存放一头大象。不过,有几种情况允许可替换性:

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

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

If one has a List object (non-generic), one can store into it anything that can be cast into Object, but there's no way of knowing at compile time what type of things one will get out of it. By contrast, if one has a generic List<Animal>, the only things one can store into it are Animal or derivatives thereof, and the compiler can know that the only things that will be pulled out of it will be Animal. The compiler can thus allow things to be pulled out of the List and stored directly into fields of type Animal without any need for run-time type checking.

Additionally, if the generic type parameter of a generic class happens to be a value type, use of generic types can eliminate the need for casting to and from Object, a process called "Boxing" which converts value-type entities into reference-type objects; boxing is somewhat slow, and can sometimes alter the semantics of value-type objects, and is thus best avoided when possible.

Note that even though an object of type SomeDerivedClass may be substitutable for TheBaseClass, in general, a GenericSomething<SomeDerivedClass> is not substitutable for a GenericSomething<TheBaseClass>. The problem is that if one could substitute e.g. a List<Giraffe> for a List<Zebra>, one could pass a List<Zebra> to a routine that was expecting to take a List<Giraffe> and store an Elephant in it. There are a couple of cases where substitutability is permitted, though:

  1. Arrays of a derived type may be passed to routines expecting arrays of base type, provided that those routines don't try to store into those arrays any items that are not of the proper derived type.
  2. Interfaces may be declared to have "out" type parameters, if the only thing those interfaces will do is return ("output") values of that type. A Giraffe-supplier may be substituted for an Animal-supplier, because all it's going to do is supply Giraffes, which are in turn substitutable for animals. Such interfaces are "covariant" with respect to those parameters.

In addition, it's possible to declare interfaces to declare "in" type parameters, if the only thing the interfaces do is accept parameters of that type by value. An Animal-eater may be substituted a Giraffe-eater, because--being capable of eating all Animals, it is consequently capable of eating all Giraffes. Such interfaces are "contravariant" with respect to those parameters.

往昔成烟 2024-12-15 19:48:13

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

另一个用途是编写更通用的实用程序类或方法来进行排序和比较等操作。

The most common example is for collections such as List, Dictionary, etc. All those standard classes are implemented using generics.

Another use is to write more general utility classes or methods for operations such as sorting and comparisons.

唠甜嗑 2024-12-15 19:48:13

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

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

Here is a Microsoft article that can be of help: http://msdn.microsoft.com/en-us/library/b5bx6xee%28v=vs.80%29.aspx

The largest benefit that I've seen is the compile-time safety of generics, as @Charlie mentioned. I've also used a generic class to implement a DataReader for bulk inserts into a database.

撩发小公举 2024-12-15 19:48:13

嗯,框架内有很多示例。想象一下,您需要实现一个整数列表,然后是一个字符串列表......然后是一个客户类别列表......等等。这将是非常痛苦的。

但是,如果您实现一个通用列表,则问题可以在更短的时间内、更少的代码中得到解决,并且您只需测试一个类。

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

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

日常程序员不会创建泛型类,但相信我,当您需要时,您会很乐意使用这样的工具进行计数。

Well, you have a lot of samples inside the framework. Imagine that you need to implement a list of intergers, and later a list of strings... and later a list of you customer class... etc. It would be very painfull.

But, if you implements a generic list the problem is solved in less time, in less code and you only have to test one class.

Maybe one day you will need to implement your own queue, with rules about the priority of every element. Then, it would be a good idea to make this queue generic if it is possible.

This is a very easy sample, but as you improve your coding skills, you will see how usefull can be to have (for example) a generic repository (It's a design patters).

Not everyday programmers make generic classes, but trust me, you will be happy to count with such tool when you need it.

羞稚 2024-12-15 19:48:13

泛型的现实世界示例。

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

现在,您被分配一项工作,将鸟移到与上面指定的笼子不同的笼子(专门为单只鸟建造)中。

(非通用列表的问题)
从旧笼子里捕捉特定的鸟并将其转移到专门为它制作的笼子是一项繁琐的任务。(哪种类型的鸟到哪个笼子--c#中的类型转换)

通用列表

现在认为您有一个单独的笼子来容纳单独的鸟,并且您想转移到专门为其设计的其他笼子。这将是一项简单的任务,您不需要花时间来完成它(不需要类型转换 - 我的意思是用笼子映射鸟)。

real world example for generics.

Think u have a cage where there are many different birds(parrot,pegion,sparrow,crow,duck) in it(non generic).

Now you are assigned a work to move the bird to seperate cages(specifically built for single bird) from the cage specified above.

(problem with the non generic list)
It is a tedious task to catch the specific bird from the old cage and to shift it to the cage made for it.(Which Type of bird to which cage --Type casting in c#)

generic list

Now think you have a seperate cage for seperate bird and you want to shift to other cages made for it. This will be a easy task and it wont take time for you to do it(No type casting required-- I mean mapping the birds with cages).

远昼 2024-12-15 19:48:13

我的朋友不是程序员,我想解释一下什么是泛型?我将向他解释如下泛型。因此,这是使用泛型的真实场景。

“隔壁街上有一家制造商。他可以制造任何汽车。但有一次他只能制造一种类型的汽车。上周,他为我制造了一辆汽车,这周他为我叔叔制造了一辆卡车。就像我说这个制造单位非常通用,可以生产客户指定的产品,但请注意,当您联系该制造商时,您必须选择您需要的汽车类型,否则根本不可能联系他。”

My friend is not a programmer and I would like to explain what is generics? I would explain him generics as below. Thus this is a real-world scenario of using generics.

"There is this manufacturer in the next street. He can manufacture any automobile. But at one instance he can manufacture only one type of automobile. Last week, he manufactured a CAR for me, This week he manufactured a TRUCK for my uncle. Like I said this manufacturing unit is so generic that it can manufacture what the customer specifies. But note that when you go to approach this manufacturer, you must go with a type of automobile you need. Otherwise approaching him is simply not possible."

策马西风 2024-12-15 19:48:13

看看微软的这篇文章。您对它们的用途和何时使用有一个很好且清晰的解释。 http://msdn.microsoft.com/en-us/library/ms172192.aspx

Have a look at this article by Microsoft. You have a nice and clear explanation of what to use them for and when to use them. http://msdn.microsoft.com/en-us/library/ms172192.aspx

眼泪都笑了 2024-12-15 19:48:13

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

在 c 或其他语言中使用委托

不确定这是否是一个特别的这是泛型使用的一个很好的例子,但我发现自己有时也会这么做。

The various generic collections are the best example of generics usage but if you want an example you might generate yourself you could take a look at my anwer to this old question:

uses of delegates in c or other languages

Not sure if it's a particularly great example of generics usage but it's something I find myself doing on occasion.

怪我闹别瞎闹 2024-12-15 19:48:13

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

如果是这种情况,那么您将创建一个基类来包含继承它的类所共有的方法和属性。例如,汽车类将包括车轮、发动机、车门等。那么您可能会创建一个 sportsCar 子类,它继承汽车类并添加扰流板、涡轮增压器等属性。

http://en.wikipedia.org/wiki/Inheritance_(面向对象编程)
在此处输入链接描述

很难理解“通用类”的含义“没有任何上下文。

Are you talking about a base class (or perhaps an abstract class)? As a class that you would build other classes (subclasses) off of?

If that's the case, then you'd create a base class to include methods and properties that will be common to the classes that inherit it. For example, a car class would include wheels, engine, doors, etc. Then maybe you'd maybe create a sportsCar subclass that inherits the car class and adds properties such as spoiler, turboCharger, etc.

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)
enter link description here

It's hard to understand what you mean by "generic class" without some context.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文