Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List of generic interfaces

If I have a generic interface with a couple of implementing classes such as:

public interface IDataElement<T>
{
    int DataElement { get; set; }
    T Value { get; set; }
}

public class IntegerDataElement : IDataElement<int>
{
    public int DataElement { get; set; }
    public int Value { get; set; }
}

public class StringDataElement : IDataElement<String>
{
    public int DataElement { get; set; }
    public String Value { get; set; }
}

Is it possible to pass a collection of the implementing classes of differing types, without having to resort to passing as object.

It does not appear to be possible to define a return values as

public IDataElement<T>[] GetData()

or

public IDataElement<object>[] GetData() 

Any suggestions?

like image 458
benPearce Avatar asked Jan 11 '10 21:01

benPearce


People also ask

What is a generic interface?

Generic Interfaces in Java are the interfaces that deal with abstract data types. Interface help in the independent manipulation of java collections from representation details. They are used to achieving multiple inheritance in java forming hierarchies. They differ from the java class.

How do you declare a generic interface?

Declaring Variant Generic Interfaces You can declare variant generic interfaces by using the in and out keywords for generic type parameters. ref , in , and out parameters in C# cannot be variant. Value types also do not support variance. You can declare a generic type parameter covariant by using the out keyword.

What is generic list in C#?

The Generic List<T> Class in C# is a collection class that is present in System. Collections. Generic namespace. This Generic List<T> Collection Class represents a strongly typed list of objects which can be accessed by using the index.

Can interfaces be generic in Java?

Java Generic Interface In similar way, we can create generic interfaces in java. We can also have multiple type parameters as in Map interface. Again we can provide parameterized value to a parameterized type also, for example new HashMap<String, List<String>>(); is valid.


2 Answers

You can certainly declare:

public IDataElement<T>[] GetData<T>()

and

public IDataElement<object>[] GetData()
  • although the latter probably isn't what you're after (your interface won't be variant even in C# 4 as it uses T in both an input and an output position; even if it were variant, you wouldn't be able to use that variance for value types). The former will require the caller to specify <T>, e.g.

    foo.GetData<string>();

Is that okay for you?

There's no way of expressing "a collection of object, each of which implements IDataElement<T> for a different T" unless you also give it a nongeneric base class, at which you could just use IList<IDataElement>. In this case the nongeneric IDataElement could have the DataElement property, leaving the Value property in the generic interface:

public interface IDataElement
{
    int DataElement { get; set; }
}

public interface IDataElement<T> : IDataElement
{
    T Value { get; set; }
}

Is that useful in your particular situation?

It's not clear how you'd want to use a collection of data elements without knowing their types... if the above doesn't help you, maybe you could say more about what you expected to do with the collections.

like image 77
Jon Skeet Avatar answered Oct 23 '22 17:10

Jon Skeet


No you can't do this - the only options are to either use a non-generic interface:

public interface IDataElement
{
    int DataElement { get; set; }
    object Value { get; set; }
}

Alternatively create a wrapper and pass that to methods that know the types they require:

public class DataElementBag
{
    private IDictionary<Type, List<object>> _elements;
    ...
    public void Add<T>(IDataElement<T> de)
    {
        Type t = typeof(T);
        if(!this._elements.ContainsKey(t))
        {
            this._elements[t] = new List<object>();
        }

        this._elements[t].Add(de);
    }

    public void IEnumerable<IDataElement<T>> GetElementsByType<T>()
    {
        Type t = typeof(T);
        return this._elements.ContainsKey(t)
            ? this._elements[t].Cast<IDataElement<T>>()
            : Enumerable.Empty<T>();
    }
}
like image 35
Lee Avatar answered Oct 23 '22 17:10

Lee