Collection of generic types

前端 未结 9 773
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-27 21:06

If I have a generic class:

public class MyClass 
{
  public T Value;
}

I want to instantiate several items such as...



        
相关标签:
9条回答
  • 2020-11-27 21:10

    Have your generic class inherit from a non-generic base, or implement a non-generic interface. Then you can have a collection of this type and cast within whatever code you use to access the collection's contents.

    Here's an example.

    public abstract class MyClass
    {
        public abstract Type Type { get; }
    }
    
    public class MyClass<T> : MyClass
    {
        public override Type Type
        {
            get { return typeof(T); }
        }
    
        public T Value { get; set; }
    }
    
    // VERY basic illustration of how you might construct a collection
    // of MyClass<T> objects.
    public class MyClassCollection
    {
        private Dictionary<Type, MyClass> _dictionary;
    
        public MyClassCollection()
        {
            _dictionary = new Dictionary<Type, MyClass>();
        }
    
        public void Put<T>(MyClass<T> item)
        {
            _dictionary[typeof(T)] = item;
        }
    
        public MyClass<T> Get<T>()
        {
            return _dictionary[typeof(T)] as MyClass<T>;
        }
    }
    
    0 讨论(0)
  • 2020-11-27 21:11

    You'll want to define a base class for MyClass, then your collections will be a List of base class. Ex:

    void Main()
    {
     var a = new MyClass<string>();
     var b = new MyClass<int>();
     var c = new List<MyBase>();
     c.Add(a);
     c.Add(b);
    
    }
    
    public class MyBase { }
    // Define other methods and classes here
    public class MyClass<T> : MyBase {
    public T Value { get; set;}
    }
    
    0 讨论(0)
  • 2020-11-27 21:12

    I have interfaces on most of my generic types with "Untyped" members:

    private interface IMyClass
    {
        object UntypedValue { get; }
    }
    
    private class MyClass<T> : IMyClass
    {
        T Value { get; set; }
    
        object UntypedValue { get { return Value; } }
    }
    

    You could also do this by the use of explicit interface implementation, but in my opinion, it is much easier by using a separate name. (There are some CA hints on explicit interface implementation as well)

    0 讨论(0)
  • 2020-11-27 21:13

    You want to have a collection of MyClass for which the value of the type parameter T is different in each instance. This is not possible in .NET; it lacks the equivalent of the Java wildcard (?). What you need to do instead is create a non-generic base class or interface, which MyClass can implement. For example:

    public interface IMyClass {
      object Value { get; set; }
    }
    public class MyClass<T> : IMyClass {
      public T Value { get; set; }
      object IMyClass.Value {
        get { return Value; }
        set { Value = (T)value; }
      }
    }
    List<IMyClass> m = new List<IMyClass> { new MyClass<string>(), new MyClass<int> };
    
    0 讨论(0)
  • 2020-11-27 21:13

    IList

    There is no way to define a generic collection that can accept any flavor of your generic class... ie IList<MyClass>. Generic classes are only a short cut for the developer to save on writing a bunch of repetitive code but at compile time each flavor of the generic class is translated into a concrete. i.e. if you have MyClass<string>, MyClass<int>, MyClass<bool> then the compiler will generate 3 seperate and distinct classes. The only way to do what you want is to have an interface for your generic.

    public interface IMyGeneric {
        Type MyType { get; set;}    
    }
    
    class MyGeneric<T> : IMyGeneric {
    
        public MyGeneric() {
            MyType = typeof(T);
        }
    
        public Type MyType {
            get; set;
        }
    }
    

    and then you can say

    IList<IMyGeneric> list = new List<IMyGeneric>();
    list.add(new MyGeneric<string>());
    list.add(new MyGeneric<int>());
    
    0 讨论(0)
  • 2020-11-27 21:15

    I think the problem here is that generic classes really aren't the same type at all. They're simply templates which create entire new types at compile time (if I understand correctly). Therefore, MyClass<int> and MyClass<string> are completely different types, according to the runtime. They might as well be MyIntClass and MyStringClass, which you obviously cannot have in the same list without boxing them first. They don't (necessarily) inherit the same base class, implement the same interfaces, or anything else. They're as different as any other two types out there, and you have to treat them as such (even though you think you know better).

    Of course, you can have them implement an interface, inherit a base object, or any of the other options already given. Take a look at commongenius' answer for a good way to do this.

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