【问题标题】:Can anybody give a good example of what to use generic classes for?任何人都可以举一个很好的例子来说明如何使用泛型类吗?
【发布时间】:2023-03-09 18:20:01
【问题描述】:

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

你有没有创建自己的泛型类,你用它做什么?

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

编程愉快!

对不起-我想我可以把这个问题写得更好一点。我熟悉通用集合。我只是想知道你自己的泛型类可以用来做什么。

感谢您提供 MSDN 链接,我在发布问题之前确实阅读了它们,但也许我错过了什么?我再看看!

【问题讨论】:

  • 泛型集合不是主要的例子之一吗?
  • 对不起,我应该提到我的意思是你创建的泛型类 :) 我熟悉 List、HashSet 等,但想知道一个虚构的泛型类可以用于什么:)不过感谢您的快速回复!
  • 您会发现,有时为特定目的创建自己的集合类会很方便
  • 你有 Nicola 的例子吗?我很想尝试:D
  • 你知道,我正在查看我正在处理的一个大型(12k LOC)项目,我只创建了三个通用函数(甚至没有类):一个显示 EF sql 字符串,一个将集合转换为DataTable,另一个用于破解.net 3.5 中EF 的in 运算符。已经为我们提供的大量泛型类(除了Action<>)几乎可以覆盖任何基础...

标签: c# class generics


【解决方案1】:

通用集合

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

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

  • 将值类型添加到非通用列表(如 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()。这要求泛型类型包含一个无参数构造器,它使我能够在不知道类型的情况下创建实例。

【讨论】:

  • 泛型也用于运行时类型安全。
  • 很多非泛型类也是非常类型安全的。
  • '当值类型被添加到非通用列表(如 ArrayList)中时,必须将值装箱。这意味着它们被存储为引用类型。这也意味着不仅值被存储在内存中,而且对它的引用也是如此,因此使用的内存比必要的多。使用通用列表时,这个问题就被消除了。 .. 并且可以被不必要且可避免的大型结构复制问题所取代,(对不起 - 无法抗拒:)。
  • 您好查理,谢谢您的回答!你如何使用你创建的泛型类(工厂)创建一个新类?
  • 谢谢你,Martin,我忘了堆栈和堆:) 很好!
【解决方案2】:

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

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

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

希望这有助于厚颜无耻。

【讨论】:

  • 从未去过瑞典或宜家,但我听说过两者的好消息。 =)
【解决方案3】:

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

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

请注意,尽管 SomeDerivedClass 类型的对象可以替代 TheBaseClass,但一般来说,GenericSomething 不能替代 GenericSomething。问题是,如果可以替代,例如对于 List 的 List,可以将 List 传递给期望获取 List 并将大象存储在其中的例程。不过,有几种情况允许可替代性:

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

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

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

        也许有一天您需要实现自己的队列,并制定有关每个元素优先级的规则。然后,如果可能的话,最好让这个队列通用。

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

        不是日常程序员都制作泛型类,但相信我,您会很乐意在需要时使用此类工具。

        【讨论】:

          【解决方案7】:

          真实世界的泛型示例。

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

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

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

          通用列表

          现在认为您有一个单独的鸟笼,并且您想转移到为它制作的其他笼子。这将是一项简单的任务,而且您不会花时间去做(不需要类型转换——我的意思是用笼子映射鸟类)。

          【讨论】:

            【解决方案8】:

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

            “下一条街有一个制造商。他可以制造任何汽车。但有一次他只能制造一种汽车。上周,他为我制造了一辆汽车,这周他为我制造了一辆卡车。大叔,就像我说的,这个制造单元太通用了,可以制造客户指定的东西。但是要注意,你去这个制造商的时候,你必须带着你需要的汽车,否则根本不可能接近他。 "

            【讨论】:

              【解决方案9】:

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

              【讨论】:

                【解决方案10】:

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

                uses of delegates in c or other languages

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

                【讨论】:

                  【解决方案11】:

                  您是在谈论基类(或者可能是抽象类)吗?作为一个你会建立其他类(子类)的类?

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

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

                  如果没有上下文,很难理解“泛型类”是什么意思。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-06-30
                    • 2010-12-21
                    • 1970-01-01
                    • 2020-06-09
                    • 2019-07-18
                    相关资源
                    最近更新 更多