2010-04-15 113 views
12

这是this question的扩展,可能甚至可能是其他问题的副本(如果是这样,请原谅我)。我see from MSDN泛型通常与集合泛型vs继承(当没有涉及集合类时)

使用

仿制 类最常见的用途是一样 链表,哈希表,栈, 队列,树和集合等在那里 操作,比如添加和无论存储的数据类型是 ,删除 中的项目都是以大致相同的方式执行的 。

我见过的例子也验证了上面的语句。

有人可以在不涉及任何集合的真实场景中有效使用泛型吗?

迂腐,我在想做出不涉及集合

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>();

这是完全有可能的有DogAnimal继承(假设非通用版本AnimalDog:Animal因此DogAnimal

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

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

+1

使用继承当过你需要扩展一个类。在你的例子中,你有Animal作为一个通用的,也就是说它可以是你分配它的类型。泛型为您的程序提供了一种使用通用界面执行操作的方法。 – Kaili 2010-04-15 04:00:51

回答

8

您可能会得到一些更好的答案,但同时考虑这一点: 泛型类暗示泛型类和参数类之间的“关系”。

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

  1. 你的狗类是不是真的本身是一个完全合格的狗/动物,因为它的“动物品质”包含在Animal (Of T)类。狗必须与父母和子女关系中的动物绑在一起。
  2. 你的动物类并不是一个真正的动物:你不能创建一种接受动物作为参数的方法,因为你不能引用全球化的Animal (Of T)类。它实际上是一个具有共同行为的类,而不是超类。你失去了在Animal (Of T)课堂以外处理动物的好处。

但在这里是怎么了,恕我直言,你应该想到仿制药: 想想MedicalDoctor(Of T)类。 Veterinarian(Of T as Animal)将继承MedicalDoctor(Of Animal)DogVeterinarian将从Veterinarian(Of Dog)继承。

要点:泛型类和参数类并不紧密耦合,相互依赖,它们并存。 (T),Func(Of TResult),Comparison(Of T),EventHandler(Of TEventArgs)),我们可以看到, ,转换器(中TSource,TResult)...和接口:的IEqualityComparer(Of T),的IComparer(Of T)已...

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的工厂。继承表示类型之间的等级关系。一只狗是一种动物,一只金毛猎犬既是狗又是动物。

3

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

泛型委托的家庭是相当不错的 - EventHandler<T>Action<...]>Func<[...]> - 这是更清楚什么是Func<int,bool>而不是一些定制IdPredicate或什么的。

+0

如果你打开它的头部,摇动它,搅动它然后斜视它*只是正确的方式*,那么你可以将'Nullable '解释为不是或者只是一个元素的集合。虽然,除非你是一个Haskell程序员,否则这可能不会发生在你身上:-) – 2010-04-15 15:00:30

1

你正在混淆继承的“是 - ”方面与泛型的“方面”。

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

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

0

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

使用GenericClass意味着this is a GenericClass object of tType-s 使用方:长方形意味着this is a Square, which is also a Rectangle

你的情况:
使用狗:动物的意思this is a Dog, which is also an Animal