C# Generics and polymorphism: an oxymoron?

前端 未结 6 1607
日久生厌
日久生厌 2020-12-16 12:17

I just want to confirm what I\'ve understood about Generics in C#. This has come up in a couple code bases I\'ve worked in where a generic base class is used to create type

相关标签:
6条回答
  • 2020-12-16 12:38

    I think you are misunderstanding the point of generics. Generics allows you to generalise a class that requires a type, but doesn't particularly care itself what type that is. For instance, a List<string> is a list of strings, but what would a List be? It's a rather useless concept to have a list of nothing.

    Each specialised class (ie, List<string>) is it's own distinct type, and the compiler treats it as such. It is possible to get at the generic type itself (typeof(List<>) for instance), but in most cases it's useless, and you certainly can't make an instance of it.

    0 讨论(0)
  • 2020-12-16 12:43

    It seems that once you introduce a Generic into an inheritance hierarchy or interface, you can no longer use that family of classes in a polymorphic way

    Correct, it's quite similar to this situation:

    class StringContainer
    {
    }
    
    class IntContainer
    {
    }
    
    StringContainer container = new IntContainer(); // fails to compile
    

    but you could do this:

    class Container
    {
    }
    
    class Container<T> : Container
    {
    }
    
    Container container = new Container<String>(); // OK
    
    0 讨论(0)
  • 2020-12-16 12:47

    I think what you're looking for is:

      SomeClass(of someType) someInstance = factory(of someType).Create();
    or maybe
      SomeClass(of someType) someInstance = factory.Create(of someType)();
    or
      SomeClass(of someType) someInstance = factory.Create();
    

    It's possible to have a set of factory classes to create different generic classes, or to have a factory with a generic type parameter to indicate which generic type it should create (note that in either case, the type parameter is the type parameter for the generic class, rather than being the generic class itself). It's also possible to have a factory which is designed to return instances of one particular form of a generic type.

    0 讨论(0)
  • 2020-12-16 12:48

    I would prefer using abstract class to act as base of all generic types.

    public abstract class SomeClass 
    {
        public abstract void SomeMethod();
    }
    
    public class SomeClass<T> : SomeClass
    {
        public override void SomeMethod() { }            
    }
    
    public class DeriveFrom<String> : SomeClass<String>
    {
        public override void SomeMethod() { base.SomeMethod(); }            
    }
    
    0 讨论(0)
  • 2020-12-16 12:51
    public Class ReflectionReport<T> 
    {
        // This class uses Reflection to produce column-based grids for reporting.  
        // However, you need a type in order to know what the columns are. 
    }
    
    ... so, in another class you have...
    
    public Class ReflectionReportProject {
        ReflectionReport<Thang> thangReport = new ReflectionReport<Thang>(); 
        ReflectionReport<Thong> thongReport = new ReflectionReport<Thong>(); 
    
    
    
        ... some more stuff ...
    
        // Now, you want to pass off all of the reports to be processed at one time....
        public ReflectionReport<????>[] ProvideReports() 
        {
            return new ReflectionReport<????>[] { thangReport, thongReport } ;
        }
    }
    
    0 讨论(0)
  • 2020-12-16 12:54

    As far as I can see, consuming code doesn't need specifics of generic class (i.e., it doesn't depends on what T is). So, why don't you introduce interface that SomeClass<T> will implement, and use instance of this interface.

    E.g.:

    public interface ISome
    {
        void SomeMethod();
    }
    
    public class SomeClass<T>: ISome
    {
        public virtual void SomeMethod(){ }
    }
    
    public void DoSomethingClienty()
    {
        Factory factory = new Factory();
        ISome someInstance = factory.Create();
    
        someInstance.SomeMethod();
    }
    

    Now, subclasses of SomeClass<T> can operate differently on different Ts, but consuming code won't change.

    0 讨论(0)
提交回复
热议问题