包含继承的匿名类型列表

时间:2016-10-04 19:43:53

标签: c# anonymous-types

假设我有以下课程

public class Dog{}
public class Bulldog : Dog{}
public class Pitbull : Dog{}

我正在尝试创建一个像这样的列表

var dogs2 = new[]
{
   new { X = new Bulldog(), Y = 10},
   new { X = new Pitbull(), Y = 20}
}.ToList();

但是,我收到以下错误No best type found for implicitly - typed array
好吧,我想这是有道理的。系统无法弄清楚X is a type of Dog`

所以,我试着这样做

var dogs1 = Enumerable.Empty<object>()
                      .Select(x => new { X = new Dog (), Y = 0 })
                      .ToList();
dogs1.Add(new { X = new Pitbull(), Y = 10 });
dogs1.Add(new { X = new Bulldog(), Y = 10 });

现在,我收到此错误cannot convert from '<anonymous type: PassingEvents.Bulldog X, int Y>' to '<anonymous type: PassingEvents.Dog X, int>'。为什么不能转换? Bulldog Dog是不是public class DogCombo { public Dog X; public int Y; } var dogs3 = new[] { new DogCombo{ X = new Bulldog(), Y = 10}, new DogCombo{ X = new Pitbull(), Y = 20} }.ToList(); 可投弃?{/ p>

有没有办法解决这个问题,而不必为新课程创作?下面的代码工作得很好

let appState = mobx.observable({
    todos: [ 'yellow', 'blue', 'red' ]
})

appState.addTodo = function() {
    appState.todos.push( 'new one' )
}

2 个答案:

答案 0 :(得分:8)

您可以将X显式地转换为Dog

类型
var dogs2 = new[]
{
   new { X = (Dog)new Bulldog(), Y = 10},
   new { X = (Dog)new Pitbull(), Y = 20}
}.ToList();

答案 1 :(得分:8)

  

为什么不能转换?不是斗牛犬可以施加给狗吗?

斗牛犬可转换为狗,是的。

您的推理如下:

  • 斗牛犬可以转换为狗
  • 因此,anonymous-type-with-Bulldog应该可以转换为anonymous-type-with-Dog。

这种推理 - 底层类型的属性应该意味着转换下类型的属性 - 称为协方差

C#支持某些受限情况下的协方差。他们是:

  • Bulldog数组可用作Dog的数组。请注意,这是 unsafe covariance ,因为您可以将Poodle放入Dog数组中,但不能放入Bulldog数组中。只有从不写入数组时,数组协方差才是安全的。

  • IEnumerable<Bulldog>可能会转换为IEnumerable<Dog>。这很安全。一系列斗牛犬是一系列狗。对于其他一些通用类型也是如此,例如IEnumerator<T>

  • 返回Bulldog的方法可以转换为返回Dog的委托类型的委托。

在某些情况下,C#还支持逆转。例如,IComparable<Dog>可能会转换为IComparable<Bulldog>。可以比较狗的东西可以比较斗牛犬。请注意,此可兑换性的方向相反,因此 contra 变体。

C#支持结构匿名类型的任何协方差(或逆变)。

理论上,C#可以根据需要支持匿名类型的逆变;这样做是安全的。之前语言和运行时团队已经投入了这个功能。简单来说,语言和运行时团队没有对该功能进行高度优先级的实际实现。

如果您认为有充分理由在匿名类型等结构类型上实现协变转换,您可以在Roslyn github论坛上开始讨论该主题,也许有一天它会实现。

  

有没有办法解决这个问题,而无需创建新类?

我建议您创建一个新类。但是,如果您想要一种便宜且简单的解决方法:只需将明确转换为Dog