泛型与继承(当不涉及集合类时)

时间:2010-04-15 03:47:01

标签: c# .net generics inheritance

这是this question的扩展,可能甚至可能与其他问题重复(如果是,请原谅我)。我see from MSDN泛型通常与集合一起使用

  

通用的最常见用途   类是集合之类的   链表,哈希表,堆栈,   队列,树木等等   添加和删​​除等操作   该系列中的物品是   以同样的方式表演   无论数据类型如何   存储

我看到的例子也证实了上述说法。

有人可以在不涉及任何收藏的现实场景中有效使用泛型吗?

小心翼翼地,我正在考虑制作一个不涉及集合的例子

public class Animal<T>
{
    public void Speak()
    {
       Console.WriteLine("I am an Animal and my type is " + typeof(T).ToString());
    }

    public void Eat()
    {
        //Eat food
    }
}

public class Dog
{
    public void WhoAmI()
    {
        Console.WriteLine(this.GetType().ToString());

    }
}         

和“狗类型的动物”将是

Animal<Dog> magic = new Animal<Dog>();

完全有可能Dog继承Animal(假设Animal的非通用版本)Dog:Animal因此Dog Animal

我想到的另一个例子是BankAccount。它可以是BankAccount<Checking>BankAccount<Savings>。这很可能是Checking:BankAccountSavings:BankAccount

是否有任何最佳实践来确定我们是否应该使用泛型或继承?

5 个答案:

答案 0 :(得分:8)

你可能会得到一些更好的答案,但同时考虑一下: 泛型类意味着泛型类和参数类之间的“关系”。

所有的狗都是动物,因此它们与所有其他动物共享某些属性/品质。如果使用继承,那么在Animal类中实现这些常见特性非常容易,并在后代类中添加特性。但是如果你使用Animal (Of Dog)实现它,那么:

  1. 你的狗类本身并不是一个完全合格的狗/动物,因为它的“动物品质”包含在Animal (Of T)类中。狗必须与亲子关系中的动物绑在一起。
  2. 你的Animal类不是真正的动物:你不能创建一些接受动物作为参数的方法,因为你不能引用全球化的Animal (Of T)类。它实际上是一个具有共同行为的类系列,而不是超类。你失去了在Animal (Of T)课程之外与动物打交道的好处。
  3. 但是,恕我直言,您应该如何看待仿制药: 想想MedicalDoctor(Of T)课程。 Veterinarian(Of T as Animal)将继承自MedicalDoctor(Of Animal)DogVeterinarian将继承Veterinarian(Of Dog)

    关键点:泛型类和参数类没有紧密耦合和共同依赖,它们共存。

    顺便说一下,如果你想看到一些很好的非收集使用泛型,请注意我们的代表:Action(Of T),Func(Of TResult),Comparison(Of T),EventHandler(Of TEventArgs),转换器(Of TSource,TResult)......和接口:IEqualityComparer(Of T),IComparer(Of T)......

答案 1 :(得分:3)

知道的一个真实世界的例子是WCF Channel Factory

从页面:

public sealed class Test
{
    static void Main()
    {
        // Code not shown.
    }

    public void Run()
    {
        // This code is written by an application developer.
        // Create a channel factory.
        BasicHttpBinding myBinding = new BasicHttpBinding();

        EndpointAddress myEndpoint = new EndpointAddress("http://localhost/MathService/Ep1");

        ChannelFactory<IMath> myChannelFactory = new ChannelFactory<IMath>(myBinding, myEndpoint);

        // Create a channel.
        IMath wcfClient1 = myChannelFactory.CreateChannel();
        double s = wcfClient1.Add(3, 39);
        Console.WriteLine(s.ToString());
        ((IClientChannel)wcfClient1).Close();

        // Create another channel.
        IMath wcfClient2 = myChannelFactory.CreateChannel();
        s = wcfClient2.Add(15, 27);
        Console.WriteLine(s.ToString());
        ((IClientChannel)wcfClient2).Close();
        myChannelFactory.Close();
    }
}

我认为泛型的方式是它们代表一个类正在作用的类型。例如,ChannelFactory构建类型为T的工厂。继承表示类型之间的层级关系。狗是动物,金毛是狗和动物。

答案 2 :(得分:3)

Nullable<T>是通用的,不是集合类,不能涉及继承,因为它与struct s相关。

通用委托家庭非常好 - EventHandler<T>Action<...]>Func<[...]> - 很多更清楚Func<int,bool>是什么而非某些自定义IdPredicate或其他。

答案 3 :(得分:1)

你将继承的“is-a”方面与泛型的“of”方面混为一谈。

泛型意味着跨类操作的相同性,而不仅仅是操作存在多态。

在动物示例中,Animal<Dog>的实例没有WhoAmI方法,而Dog : Animal的实例会有。{/ p>

答案 4 :(得分:0)

请在你的情况下使用继承。
如果一个类可以被另一个类正确描述[例如,一个正方形可以描述为一个矩形],则该正方形应该从矩形任务继承/扩展。否则,你就陷入了混乱。

使用GenericClass表示this is a GenericClass object of tType-s 使用Square:Rectangle表示this is a Square, which is also a Rectangle

在你的情况下:
使用Dog:Animal表示this is a Dog, which is also an Animal