繁体   English   中英

演员班<T>上课

[英]Cast Class<T> to Class

我有一个简单的类,它看起来像这样:

public class MyClass<T> 
{
    public int Status { get; set; }
    public T Value { get; set; }
}

为方便起见,我有另一个继承自MyClass<string> ,以允许我在没有通用参数的情况下构造MyClass ,例如:

public class MyClass : MyClass<string> { }

我希望能够将MyClass<T>MyClass ,并且默认情况下这似乎不起作用。 此示例强制转换会引发以下错误:

MyClass<string> withT = new MyClass<string> { Status = 1, Value = "Somevalue" };
MyClass withoutT = (MyClass)withT;

无法将“MyClass`1[System.String]”类型的对象转换为“MyClass”

所以我相信我需要实现一些隐式/显式转换逻辑,如本答案所述。

我已更新MyClass<T>如下,但仍然抛出相同的错误:

public class MyClass<T>
{
    public int Status { get; set; }
    public T Value;

    public static implicit operator MyClass(MyClass<T> myClass)
    {
        return new MyClass
        {
            Status = myClass.Status,
            Value = myClass.Value.GetType() == typeof(string) ? myClass.Value.ToString() : null
        };
    }
}

谁能帮忙指出我哪里出错了?

为什么不使用工厂? 这是一个非常简单的例子:

public static class MyClass
{
    public static MyClass<string> Create(string s, int status)
    {
        return new MyClass<string>(s, status);
    }
}

...

var x = MyClass.Create("Foo", 0);

Jon Skeet 的评论是对的。

完全扔掉泛型。 你能做这个吗?

class X {}
class Y : X {}
...
var x = new X();
var y = (Y)x;

你不能。 X不是Y 同样, MyClass<string>不是MyClass

更进一步,您的转换代码仍然无法像您所说的那样工作,并且尝试以其他方式(例如,专门使用string键入)定义隐式或显式转换运算符甚至无法编译。

解决方案

  • 做l33t的解决方案。 这是最直接的。
  • 做@ja72 的解决方案。 它有效并且是最通用的。
  • 创建您自己的静态方法进行转换或创建扩展方法进行转换。
  • MyClass<string>中断MyClass的继承并定义您的运算符。 是的,这意味着一些冗余代码。

考虑使MyClass<T>成为一个必须继承的类(使用abstract关键字),这样它就不能被实例化。 这样你只能从派生类创建对象,你可以向下转换到基类。

此外,如果您想要对派生类型(用于转换)的类型引用,则将其包含在类型参数中。 添加一个从MyClass<T>继承的TDerived ,如下所示:

public abstract class MyClass<TDerived, TValue> where TDerived : MyClass<TDerived, TValue>
{
    protected MyClass(int status, TValue value)
    {
        this.Status = status;
        this.Value = value;
    }
    public int Status { get; set; }
    public TValue Value { get; set; }

    public static implicit operator TDerived(MyClass<TDerived, TValue> myClass)
        => myClass as TDerived;
}

public class SpecificClass : MyClass<SpecificClass, string>
{
    public SpecificClass(int status, string value) : base(status, value)
    {
        // The ONLY way to instantiate a MyClass<> is from a derived class
        // such as this.
    }        
}

class Program
{
    static void Main(string[] args)
    {
        MyClass<SpecificClass, string> my_class = new SpecificClass(-1, "ABC");

        SpecificClass my_specific = my_class;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM