无法将null分配给array类型的匿名属性

pet*_*loy 26 c# linq anonymous-types

我有任何Pilot带有(Hanger)属性的()对象数组,该属性可以为null,它本身具有(List<Plane>)属性.出于测试目的,我想简化并将其"展平"为具有属性PilotName(字符串)和Planes(数组)的匿名对象,但不确定如何处理null Hanger属性或空PlanesList.

(为什么是匿名对象?因为我正在测试的API的对象是只读的,我希望测试是'声明性的':自包含,简单和可读......但我对其他建议持开放态度.我也是我想了解更多有关LINQ的信息.)

class Pilot
{
    public string Name;
    public Hanger Hanger;
}

class Hanger
{
    public string Name;
    public List<Plane> PlaneList;
}

class Plane
{
    public string Name;
}

[TestFixture]
class General
{
    [Test]
    public void Test()
    {
        var pilots = new Pilot[]
        {
            new Pilot() { Name = "Higgins" },
            new Pilot()
            {
                Name = "Jones", Hanger = new Hanger()
                {
                    Name = "Area 51",
                    PlaneList = new List<Plane>()
                    {
                        new Plane { Name = "B-52" },
                        new Plane { Name = "F-14" }
                    }
                }
            }
        };

        var actual = pilots.Select(p => new
        {
            PilotName = p.Name,
            Planes = (p.Hanger == null || p.Hanger.PlaneList.Count == 0) ? null : p.Hanger.PlaneList.Select(h => ne
            {
                PlaneName = h.Name
            }).ToArray()
        }).ToArray();

        var expected = new[] {
            new { PilotName = "Higgins", Planes = null },
            new
            {
                PilotName = "Jones",
                Planes = new[] {
                    new { PlaneName = "B-52" },
                    new { PlaneName = "F-14" }
                }
            }
        };

        Assert.That(actual, Is.EqualTo(expected));
    }
Run Code Online (Sandbox Code Playgroud)

当前的问题是线路expected... Planes = null错误,

无法指定匿名类型属性,但承认潜在的问题可能是使用nullactual使用null不摆在首位的最佳方法.

任何想法如何可以分配在空阵列expected或采取不同的方式比nullactual

And*_*tan 55

您必须使用类型化的 null:

(List<Plane>)null
Run Code Online (Sandbox Code Playgroud)

要么

(Plane[])null
Run Code Online (Sandbox Code Playgroud)

否则,编译器不知道您希望匿名类型的成员是什么类型.

更新 正如@AakashM正确地指出的那样 - 这解决了你给null匿名成员分配一个问题的问题- 但实际上并没有编译 - 如果确实如此,它将不允许你引用这些成员.

修复就是这样做(不幸的是null,匿名Planes数组都需要转换:

var expected = new[] {
  new { 
          PilotName = "Higgins", 
          Planes = (IEnumerable)null
      },
  new {
          PilotName = "Higgins", 
          Planes = (IEnumerable)new [] {
                              new { PlaneName = "B-52" },
                              new { PlaneName = "F-14" } 
                          }
      }
};
Run Code Online (Sandbox Code Playgroud)

因此请IEnumerable用作成员类型.您也可以使用,IEnumerable<object>但效果将相同.

或者 - 您可以使用IEnumerable<dynamic>常见类型 - 这可以让您这样做:

Assert.AreEqual("B-52", expected[1].Planes.First().PlaneName);
Run Code Online (Sandbox Code Playgroud)

  • 为了完整起见:“null as Plane[]”也可以工作。 (2认同)

Aak*_*shM 36

发生了两件事:

首先,当你构建使用匿名类型的实例new { Name = Value},以建设编译器需要能够制定出类型类型Value.只是null它自己没有类型,所以编译器不知道给你的Planes成员什么类型.

现在,如果你使用命名类型作为值,你可以说(type)null并完成,但是因为你想要一个另一个匿名类型的数组,没有办法引用它(它是匿名的!).

那你如何null输入一个匿名类型的数组呢?好吧,C#规范保证了具有相同名称和类型(以相同顺序!)的成员的匿名类型是统一的 ; 也就是说,如果我们说

var a = new { Foo = "Bar" };
var b = new { Foo = "Baz" };
Run Code Online (Sandbox Code Playgroud)

然后ab具有相同类型.我们可以使用这个事实来得到我们适当的类型null:

var array = (new[] { new { PlaneName = "" } });
array = null;
Run Code Online (Sandbox Code Playgroud)

它不漂亮,但它的工作原理 - 现在array有正确的类型null 价值.所以这个编译:

        var array = new[] { new { PlaneName = "" } };
        array = null;

        var expected = new[]
                           {
                               new
                                   {
                                       PilotName = "Higgins",
                                       Planes = array
                                   },
                               new
                                   {
                                       PilotName = "Higgins",
                                       Planes = new[]
                                                    {
                                                        new { PlaneName = "B-52" },
                                                        new { PlaneName = "F-14" }
                                                    }
                                   }
                           };
Run Code Online (Sandbox Code Playgroud)

  • 另一种方法是内联`new [] {new {PlaneName =""}} .Take(0).ToArray() (3认同)

Via*_*nov 9

只需使用default(Plane[])而不是null.