【问题标题】:How can I explicitly convert this derived class in .NET 2?如何在 .NET 2 中显式转换此派生类?
【发布时间】:2012-10-18 21:47:34
【问题描述】:

尽管搜索了 Google 和 SO,但我似乎无法在 .NET2.0 中找到如何执行此操作。

假设我有以下课程:

public class Fruit {
    prop string Color {get; set;}
}

public class Apple : Fruit {
    public Apple() {
        this.Color = "Red";
    }
}

public class Grape: Fruit {
    public Grape() {
        this.Color = "Green";
    }
}

现在我想这样做:

public List<Fruit> GetFruit() {
    List<Fruit> list = new List<Fruit>();
    // .. populate list ..
    return list;
}    


List<Grape> grapes = GetFruit();

但我当然会得到Cannot implicitly convert type Fruit to Grape

我意识到这是因为如果我这样做了,我真的会把事情搞砸:

List<Grape> list = new List<Grape>();
list.add(new Apple());

因为两者都是FruitApple 不是Grape。所以这是有道理的。

但我不明白为什么我不能这样做:

List<Fruit> list = new List<Fruit>();
list.add(new Apple());
list.add(new Grape());

至少,我需要能够:

List<Fruit> list = new List<Fruit>();
list.add(new Apple());   // will always be Apple
list.add(new Apple());   // will always be Apple
list.add(new Apple());   // will always be Apple

关于如何在.NET2 中执行此操作的任何想法?

谢谢

编辑

对不起,我弄错了。事实上我可以做到:

List<Fruit> list = new List<Fruit>();
list.add(new Apple());
list.add(new Grape());

.FindAll.Convert 成功了。

【问题讨论】:

  • prop string Color {get; set;} 道具?
  • “但我不明白为什么我不能这样做” - 据我所知,你应该能够做到这一点(假设你更正了 Add 和使Fruit 可编译)
  • “但我不明白为什么我不能这样做:” - 你可以,只要你使用Add而不是add(不存在);最后的所有例子都很好。
  • @Damien_The_Unbeliever 是对的...我已经在 .NET 2.0 上进行了尝试,以确保 100% 可以正常工作
  • @asawyer 是的。我输入了“prop”,因为这是 Visual Studio 上的快捷方式。哈哈。我已经习惯了打字,以至于它不假思索地就出来了。大声笑和马克和保罗。你说的都是对的。我可以做到这一点。那是我的一个错误。

标签: .net generics inheritance .net-2.0 derived-class


【解决方案1】:

由于您首先需要.Net 2.0 中的特定内容,因此我将使用FindAll 过滤每个内容,然后使用ConvertAll

List<Grape> grapes = list
  .FindAll(delegate(Fruit f) { return f is Grape; })
  .ConvertAll<Grape>(delegate(Fruit f) { return f as Grape; });

至于你的问题:

但我不明白为什么我不能这样做:

List<Fruit> list = new List<Fruit>();
list.Add(new Apple());
list.Add(new Grape());

你可以这样做,它是完全有效的,你是不是输入错误(添加与添加)?

【讨论】:

  • 我错了,不能插入葡萄和苹果。您的 FindAll 和 ConvertAll 建议似乎是满足我需求的方法。谢谢!
【解决方案2】:

列表永远不会是协变的,即使在更高版本的 .NET 中也是如此(可枚举是)。

list.Add(new Apple()) 等应该已经可以正常工作 - 没有问题。

对于作业,您可能需要执行以下操作:

List<Grape> grapes = GetFruit().ConvertAll(x => (Grape)x);

或在较旧的编译器上:

List<Grape> grapes = GetFruit().ConvertAll<Grape>(delegate(Fruit x) {
    return (Grape)x;
});

(语义相同)

【讨论】:

    【解决方案3】:

    我 100% 确定您可以做到这一点:

    List<Fruit> list = new List<Fruit>();
    list.add(new Apple());
    list.add(new Grape());
    

    您为什么要坚持使用 .net 2.0 有什么特别的原因吗?

    使用 .net 3.5 您有两种可能性:

    List<Apple> apples = list.OfType<Apple>().ToList();
    

    这将过滤您的列表并返回一个苹果列表。 你还有:

    List<Apple> apples = list.Cast<Apple>().ToList();
    

    不会过滤,而是假设列表中的所有元素都是苹果(如果不是,则抛出和 InvalidCastException)。

    【讨论】:

    • 我必须坚持使用 .net 2,因为这是一个无法升级的遗留 GUI 应用程序。它运行的大多数机器仍在运行带有 .net 2 的 XP。
    【解决方案4】:

    如果您确定葡萄只会返回 Grape 对象,您可以使用 LINQ Cast:

    Enumerable.Cast Method

    List<Garapes> grapes = GetFruit().Cast<Grape>().ToList();
    

    您也可以使用 LINQ Where 在进行转换之前只获取葡萄果实

    Where(f =&gt; f is Grape)

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-24
      相关资源
      最近更新 更多