将非泛型类型转换为泛型类型

5

我有这个类:

class Foo { 
    public string Name { get; set; }
}

并且这个类

class Foo<T> : Foo {
    public T Data { get; set; }
}

这是我想做的事情:

public Foo<T> GetSome() {
    Foo foo = GetFoo();

    Foo<T> foot = (Foo<T>)foo;
    foot.Data = GetData<T>();
    return foot;
}

将Foo转换为Foo<T>的最简单方式是什么?我不能直接进行强制转换(这会导致InvalidCastException),也不想手动复制每个属性(在我的实际用例中,有多个属性)如果没有必要的话。用户定义的类型转换是否是正确的选择?


GetFoo 是什么样子? - Gabe
这只是一个桩代码。将其替换为新的 Foo(); - John Sheehan
2
如果是这种情况,那么你有一个根本性的问题。类型不能变成其他类型。 - leppie
1
只是一个简单的问题:如果您创建了一个简单的“Foo”对象,您如何将其转换为“Foo<T>”?它应该从哪里获取额外的“Data”? - Oliver
想知道如果我让Foo和Foo<T>都继承一个抽象基类FooBase,是否会更容易实现共享属性... - John Sheehan
3个回答

4
您可以在 Foo<T> 中创建一个显式的转换来处理 Foo。
class Program
{
    static void Main()
    {
        Foo foo = new Foo();
        foo.Name = "Blah";
        Foo<int> newfoo = (Foo<int>)foo;
        Console.WriteLine(newfoo.Name);
        Console.Read();
    }
}

class Foo
{
    public string Name { get; set; }
    public object Data { get; set; }
}

class Foo<T>
{
    public string Name { get; set; }
    public T Data { get; set; }
    public static explicit operator Foo<T>(Foo foo)
    {
        Foo<T> newfoo = new Foo<T>();
        newfoo.Name = foo.Name;
        return newfoo;
    }
}

编辑: 这仅适用于没有继承的情况。似乎您无法从基类向派生类进行用户定义的转换。请参见此处 Mads Torgersen的评论

我们已经预定义了基类和派生类之间的转换(强制转换),为了使语言的语义可预测,我们不允许您搞砸它

看起来您可能需要定义一个方法将Foo转换为Foo<T>。或者放弃继承。两种解决方案都不是特别理想。


好的,这正是我所想的。只是在寻找确认 :) 谢谢 - John Sheehan
这个不行:"不允许将用户定义的转换应用于基类或从基类进行转换"。 - John Sheehan
@John Sheehan:他的例子是可行的,但如果你有继承就不行了。 - leppie
很有趣,我没有注意到继承。我的例子没有使用它也能工作。回到绘图板上重新思考。 - Anthony Pegram
一个好的想法...我之前不知道...谢谢让我学到了新东西 (+1) - The King

1

使用复制构造函数。Foo 实现:

class Foo {
     Foo(Foo copy) { ... }
}

Foo应该使用以下内容进行构建:

class Bar<T> : Foo {
      Bar(Foo copy) : base(copy) { ... }
}

是的。你需要逐个成员复制,并且这应该在“复制构造函数”中完成。


1

如果你遇到了 InvalidCastException,那么 GetFoo() 返回的 Foo 类型不是 Foo<T>。你需要将 T 或者 typeof(T) 传递给该函数,以便它可以返回一个 Foo<T> 的实例。


类型转换异常出现在 Foo<T> foot = (Foo<T>)foo; 这一行,而不是从 GetFoo() 返回的内容;那只是一个演示结构的存根。 - John Sheehan
我的观点仍然站得住脚。看问题来自哪里,而不是它发生在哪里。 - leppie
然而,这并没有回答更大的问题。我已经知道转换是不可能的,这只是我的意图的演示。 - John Sheehan
@John Sheehan:那么请看我在答案中的第二句话。还有其他选项,比如将Foo<T>的新实例传递到GetFoo方法中以填充它。如果不是这种情况,请澄清你的问题。 :) - leppie
或者将 GetFoo 泛型化:Foo<T> GetFoo<T>() - Sam Harwell
@280Z28:你可能不想要那个 :) void PopulateFoo(Foo f) 会更好。 - leppie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接