Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accept only types, which declaring some interface

How to do things like this

List<Type:IMyInterface> a = new List<Type:IMyInterface>;
a.Add(typeof(MyClass1)); //MyClass1..3 implementing IMyInterface
a.Add(typeof(MyClass2));
a.Add(typeof(MyClass3));
IMyInterface c = default(a[1]); //create MyClass2 object
a.Add(typeof(Object)); //must fail

without constructing object first or checking type later?

like image 566
Arman Hayots Avatar asked Mar 06 '26 00:03

Arman Hayots


2 Answers

what you want is not directly supported in C#. since Constraints on Type parameter can only be specefied on constructor, inheritance hierarchy, interface implementation and a few others. more details

you can do it in a different way, however in this approach there is no compile time error:

public interface IMyConstraint { void Do(); }

public class MyClass: IMyConstraint
{
    public void Do()
    {
    }
}

// Inherit from the List class to add some functionality to it
public class MyTypeList<T> : List<T> where T : System.Type
{
    public MyTypeList()
    {

    }

    // use new keyword to prevent client from using the List.Add method.
    public new void Add(T type)
    {
        // here you check if the type is implementing the interface or not
        if (!typeof(IMyConstraint).IsAssignableFrom(type))
        {
            // if it dose not implement the interface just throw an exception
            throw new InvalidOperationException();
        }
        // call the original List.Add method            
        base.Add(type);
    }
}
like image 151
SHM Avatar answered Mar 07 '26 14:03

SHM


You can do this if you know the types involved statically:

public class TypeList<T>
{
    private readonly List<Type> types = new List<Type>();
    public void Add<D>() where D : T, new()
    {
        this.types.Add(typeof(D));
    }

    public T NewAt(int index)
    {
        return (T)Activator.CreateInstance(this.types[index]);
    }
}

then you can do:

var a = new TypeList<IMyInterface>;
a.Add<MyClass1>();
a.Add<MyClass2>();
a.Add<MyClass3>();
IMyInterface c = a.NewAt(1);
a.Add<object>(); //won't compile
like image 28
Lee Avatar answered Mar 07 '26 14:03

Lee



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!