Collection of generic types

前端 未结 9 778
爱一瞬间的悲伤
爱一瞬间的悲伤 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:16

    The only way I can think of, off the top of my head is as follows (wrapped up in a Console app for testing):

    class Program
    {
        static void Main(string[] args)
        {
            var x = new MyClass<string>() { Value = "34" };
            var y = new MyClass<int>() { Value = 3 };
    
            var list = new List<IMyClass>();
            list.Add(x);
            list.Add(y);
    
            foreach (var item in list)
            {
                Console.WriteLine(item.GetValue);
            }
        }
    
        private interface IMyClass
        {
            object GetValue { get; }
        }
    
        private class MyClass<T> : IMyClass
        {
            public T Value;
    
            public object GetValue
            {
                get
                {
                   return Value;
                }
            }
        }
    }
    

    i.e. Have MyClass implement an empty interface and then create your collections as one that holds instances of classes that implement that interface.

    Update: I've added a "GetValue" method to the interface that allows you to access the "Value" of the MyClass instance as an Object. This is about as good as it's going to get, afaik, if you want to have a collection that holds mixed types.

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

    Since .Net 3 there has been a CompositeCollection class which allows multiple unique items or even collections to be contained within. It is used by WPF developers to store and display differing items in Xaml. But that doesn't mean it can't be used in non WPF situations.

    Here is an example where I store differing things from strings to decimals and extract and enumerate over all items, then items of a specific type:

    CompositeCollection cc = new CompositeCollection();
    
    cc.Add(1);
    cc.Add("Item One");
    cc.Add(1.0M);
    cc.Add(1.0);
    cc.Add("Done");
    
    Console.WriteLine ("Every Item");
    
    foreach (var element in cc)
        Console.WriteLine ("\t" + element.ToString());
    
    Console.WriteLine (Environment.NewLine + "Just Strings");
    
    foreach (var str  in cc.OfType<string>())
        Console.WriteLine ("\t" + str);
    
    /* Outputs:
    
    Every Item
      1
      Item One
      1.0
      1
      Done
    
    Just Strings
      Item One
      Done
    
    */
    
    0 讨论(0)
  • 2020-11-27 21:18

    I believe your collection would all have to be of the same MyClass type (as in T would have to be the same), because the compiler won't know what types you'd added to which elements in the collection.

    In other words, if you were to add 2 elements to a list:

    list.Add(new MyClass<string>());
    list.Add(new MyClass<int>());
    

    then try to reference one:

    var myItem = list[1];
    

    The compiler doesn't know what generic was assigned to the MyClass list at element 1, because the elements are added at runtime, but the generics are determined at compile time.

    I'm pretty sure that what you want to do can't be done.


    If you know the number of elements in advance, perhaps you could use a Tuple?

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