Generic type in C #: limiting the type of a parameter as a collection

I need to write a generic class where the type parameter must be something that implements ICollection<T>. Inside, MyClassI need the type of the collection item (in the code snippet marked as ???).

class MyClass<TCollection> where TCollection : ICollection<???>
{
  // ...

  public void store(??? obj) { /* put obj into collection */ }

  // ...
}

Often the collection will actually be a dictionary. Sometimes it will be something as simple as a list.

I know exactly how to do this in C ++. How can I do this, is it C #?

+3
source share
5 answers

The simplest thing is just to specify only the type of element and hard code ICollection<T>where you need it, for example

class MyClass<T> {

    private ICollection<T> _items;

    public MyClass(ICollection<T> items) {
        _items = items;
    }

    public void Store(T obj) {
        _items.Add(obj);
    }

    public ICollection<T> Items {
        get {
            return _items;
        }
    }
}

, . "" ( ) , . .

RE-EDIT (3- ): typedef , . , , .

1 - :

// This KeyValuePair was being used to simulate a tuple. We don't need to simulate a tuple when we have a concrete class.
class BazAndListOfWrgl {
    Baz Baz { get; set; }
    List<Wrgl> Wrgls { get; set; }
}

// Simple typedef.
class BazAndListOfWrglDictionary : Dictionary<Bar, BazAndListOfWrgl> { }

2 - . . , , ( ).

using OuterDictionary = System.Collections.Generic.Dictionary<MyNamespace.Foo, MyNamespace.BazAndListOfWrglDictionary>;
using OuterDictionaryItem = System.Collections.Generic.KeyValuePair<MyNamespace.Foo, MyNamespace.BazAndListOfWrglDictionary>;

3 - :

class Program {

    static void Main() {

        // List-based example.
        var listWrapper = new MyClass<BazAndListOfWrgl>(new List<BazAndListOfWrgl>());
        listWrapper.Store(new BazAndListOfWrgl());
        Console.WriteLine(listWrapper.Items.Count);

        // Dictionary-based example.
        var dictionaryWrapper = new MyClass<OuterDictionaryItem>(new OuterDictionary());
        dictionaryWrapper.Store(new OuterDictionaryItem(new Foo(), new BazAndListOfWrglDictionary()));
        Console.WriteLine(dictionaryWrapper.Items.Count);

    }
}

: BazAndListOfWrglDictionary , . OuterDictionary OuterDictionaryItem , .

+3

, :

class MyClass<TCollection, TElement> where TCollection : ICollection<TElement>
{
  // ...

  public void store(TElement obj) { }

  // ...
}

TCollection ? TElement?

+5

:

class MyClass<TCollection,T> where TCollection : ICollection<T> , new()
{
    private TCollection collection;           

    public MyClass()
    {
        collection = new TCollection();
    }

    public void Store(T obj)
    {
        collection.Add(obj);
    }

    public TCollection Items
    {
        get { return collection; }
    }
}

:

MyClass<List<string>, string> myclass = new MyClass<List<string>, string>();
myclass.Store("First element");
myclass.Store("Second element");
myclass.Items.ForEach(s => Console.WriteLine(s));

EDIT: T , , () typedef.

using HugeType = System.Collections.Generic.Dictionary<int, string>; // Example 'typedef'
...

//Create class, note the 'typedef' HugeType
MyClass<List<HugeType>, HugeType> myclass = new MyClass<List<HugeType>, HugeType>();
//Fill it
HugeType hugeType1 = new HugeType();
hugeType1.Add(1, "First");
hugeType1.Add(2, "Second");
HugeType hugeType2 = new HugeType();
hugeType1.Add(3, "Third");
hugeType1.Add(4, "Fourth");
myclass.Store(hugeType1);
myclass.Store(hugeType2);
//Show it values.
myclass.Items.ForEach(element => element.Values.ToList().ForEach(val => Console.WriteLine(val)));
+2

?:

class MyClass<T, TCollection>  where T: YourTypeOrInterface
                               where TCollection : ICollection<T>
{
    public void store(T obj) { }
}

, , , , :

class MyClass<TCollection> where TCollection : System.Collections.ICollection
{

    TCollection Collection;

    public void Store<T>(T obj) 
    {
        ((ICollection<T>)this.Collection).Add(obj);
    }

}
+1

- , TCollection?

, , TCollection, ICollection<T>?

It is assumed that your clients will implement the interface ICollection<T>, so it does not affect your object; You will always call only on this interface, and not on their specific type. Thus, your object should only know the type of element stored in the collection.

Under this premise, a class can be written as follows:

public class MyClass<T>
{
    public MyClass(ICollection<T> collection) 
    { 
        /* store reference to collection */ 
    }

    // ...

    public void store(T obj) 
    { 
        /* put obj into collection */ 
    }

    // ...
}
+1
source

Source: https://habr.com/ru/post/1721378/


All Articles