代码之家  ›  专栏  ›  技术社区  ›  0xDED

如何将泛型类强制转换为对象的泛型类?

  •  -1
  • 0xDED  · 技术社区  · 2 年前

    假设您有两个类:

    public abstract class Foo<T> {
        public abstract T DoSomething();
    }
    
    public class FooInt : Foo<int> {
        public override int DoSomething() {
            return 42;
        }
    }
    

    我想把FooInt变成Foo<对象>。 并且很难重构代码,因为我有一个List<Foo<对象>>存储所有Foo类实例。 我确实想保留FooInt的覆盖。


    我试过这样做:

    public static implicit operator Foo<object>(Foo<T> field) { return (Foo<object>)field; }
    

    但我得到了一个Overflow Exception,因为它自称为Overflow Exception。然后我试了一下:

    public static implicit operator Foo<object>(Foo<T> field) { return (field as Foo<object>)!; }
    

    但结果为空。我试过了:

    public static implicit operator Foo<object>(Foo<T> field) { return (Foo<object>)(object)field;}
    

    但这给出了一个Invalid Cast异常。我也试着去掉石膏,但也没用。

    2 回复  |  直到 2 年前
        1
  •  2
  •   JonasH    2 年前

    你可以申报 covariant interface :

    public interface IFoo<out T>
    {
        T DoSomething();
    }
    public class Foo<T> : IFoo<T>
    {
        public T DoSomething() => default;
    }
    

    这样你就可以写作了 IFoo<object> a = new Foo<MyClass>(); 。但仍然不允许 IFoo<object> b = new Foo<int>() 。为此,我认为您需要一个适配器:

    public class FooObjectAdapter<T>(IFoo<T> foo) : IFoo<object>
    {
        public object DoSomething() => (object)foo.DoSomething();
    }
    IFoo<object> b = new FooObjectAdapter<int>(new Foo<int>());
    
        2
  •  1
  •   TimChang    2 年前

    @Fildor评论,像这样

    public interface IFoo
    {
        void DoSome();
    }
    
    public abstract class Foo<T> : IFoo
    {
        public abstract T DoSomething();
        public void DoSome()
        {
            DoSomething();
        }
    }
    
    public class FooInt : Foo<int>
    {
        public override int DoSomething()
        {
            return 42;
        }
    }
    public class FooDouble : Foo<double>
    {
        public override double DoSomething()
        {
            return 42.0;
        }
    }
    
    
    List<IFoo> list = new List<IFoo>()
       {
           new FooInt(),
           new FooDouble()
       };
     foreach (var item in list)
     {
         item.DoSome();
     }