InvalidCastException on Generics

前端 未结 2 630
太阳男子
太阳男子 2020-12-18 09:09

Coming from the Java world, programming with generics and C# is often a headache. Like this one:

interface ISomeObject { }
class SomeObjectA : ISomeObject {          


        
相关标签:
2条回答
  • 2020-12-18 09:52

    Sometimes it is useful to let a generic interface implement a non generic one to circumvent the missing <?>

    interface ISomething
    {
        object GetObject();
    }
    
    interface ISomething<T> : ISomething
        where T : ISomeObject
    {
        T GetObject();
    }
    
    public class SomeImplementation<T> : ISomething<T>
    {
        public T GetObject()
        {
            ...
        }
    
        object ISomething.GetObject()
        {
            return this.GetObject(); // Calls non generic version
        }
    }
    

    A collection can then be typed with the non generic interface

    var list = new List<ISomething>();
    list.Add(new SomeImplementation<string>());
    list.Add(new SomeImplementation<int>());
    
    0 讨论(0)
  • 2020-12-18 09:57

    Out keyword will be a fix, if your ISomething only have methods that return T

    interface ISomething<out T> where T : ISomeObject
    

    when creating a generic interface, you can specify whether there is an implicit conversion between interface instances that have different type arguments.

    It is called Covariance and Contravariance

    Eric Lippert have a good series of articles why we need to think about this, here interface variance is used

    Here is my code, which works as expected for me

    interface ISomeObject { }
    class SomeObjectA : ISomeObject { }
    class SomeObjectB : ISomeObject { }
    
    
    interface ISomething<out T> where T : ISomeObject
    {
        T GetObject();
    }
    class SomethingA : ISomething<SomeObjectA>
    {
        public SomeObjectA GetObject() { return new SomeObjectA(); }
    }
    class SomethingB : ISomething<SomeObjectB>
    {
        public SomeObjectB GetObject() { return new SomeObjectB(); }
    }
    
    
    class SomeContainer
    {
    
        private ISomething<ISomeObject> Something;
    
        public void SetSomething<T>(ISomething<T> s) where T : ISomeObject
        {
            Something = (ISomething<ISomeObject>)s;
        }
    }
    
    
    class TestContainerSomething
    {
        static public void Test()
        {
            SomeContainer Container = new SomeContainer();
            Container.SetSomething<SomeObjectA>(new SomethingA());
        }
    }
    
    0 讨论(0)
提交回复
热议问题