C# 无法将 null 分配给数组类型的匿名属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14317161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Cannot assign null to anonymous property of type array
提问by petemoloy
I have any array of (Pilot
) objects with a (Hanger
) property, which may be null, which itself has a (List<Plane>
) property. For testing purposes, I want to simplify and 'flatten' this to an anonymous object with properties PilotName
(string) and Planes
(array) but not sure how to handle a null Hanger
property or an empty PlanesList
.
我有任何Pilot
具有 ( Hanger
) 属性的 ( ) 对象数组,它可能为 null,它本身具有 ( List<Plane>
) 属性。出于测试目的,我想将其简化并“扁平化”为具有属性PilotName
(字符串)和Planes
(数组)的匿名对象,但不确定如何处理 nullHanger
属性或空的PlanesList
.
(Why anonymous objects? Because the objects of the API I'm testing are read only and I want the test to be 'declarative': self contained, simple and readable... but I'm open to other suggestions. Also I'm trying to learn more about LINQ.)
(为什么是匿名对象?因为我正在测试的 API 的对象是只读的,我希望测试是“声明性的”:自包含、简单和可读......但我愿意接受其他建议。我也是我正在尝试了解有关 LINQ 的更多信息。)
example
例子
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));
}
The immediate problem is that the line expected... Planes = null
errors with,
直接的问题是线路expected... Planes = null
错误,
Cannot assign to anonymous type property but admit the underlying problem may be that using
null
inactual
is usingnull
is not the best approach in the first place.
不能分配给匿名类型属性,但承认潜在的问题可能是 using
null
inactual
is usingnull
不是最好的方法。
Any ideas how to either assign the null array in expected
or take a different approach than null
in actual
?
任何想法如何分配空数组 inexpected
或采用与null
in不同的方法actual
?
采纳答案by AakashM
There are two things happening:
有两件事发生:
Firstly, when you construct an instance of an anonymous type using new { Name = Value}
, in order to build the type the compiler needs to be able to work out the typeof Value
. Just null
on its own doesn't have a type, so the compiler wouldn't know what type to give your Planes
member.
首先,当你构建使用匿名类型的实例new { Name = Value}
,以建设编译器需要能够制定出类型类型的Value
。就null
其本身而言没有类型,因此编译器不知道该给您的Planes
成员什么类型。
Now, if you were using a named type for the value, you could just say (type)null
and be done, BUT because you want an array of another anonymous type, there's no way to referto is (it's anonymous!).
现在,如果您使用命名类型作为值,您可以说(type)null
并完成,但是因为您想要另一个匿名类型的数组,所以无法引用is(它是匿名的!)。
So how do you get null
typed as array of an anonymous type? Well, the C# spec guarantees that anonymous types with members the same names and types (in the same order!) are unified; that is, if we say
那么如何将null
类型输入为匿名类型的数组呢?好吧,C# 规范保证具有相同名称和类型(以相同顺序!)成员的匿名类型是统一的;也就是说,如果我们说
var a = new { Foo = "Bar" };
var b = new { Foo = "Baz" };
then a
and b
have the same type. We can use this fact to get our suitably-typed null
thus:
然后a
和b
具有相同的类型。我们可以使用这个事实来获得我们的适当类型null
:
var array = (new[] { new { PlaneName = "" } });
array = null;
It's not pretty but it works - now array
has the right typebut a null
value. So this compiles:
它不漂亮但它有效 - 现在array
有正确的type但一个null
value。所以这编译:
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" }
}
}
};
回答by Andras Zoltan
You have to use a typednull:
您必须使用类型化的null:
(List<Plane>)null
Or
或者
(Plane[])null
Otherwise the compiler has no idea what type you want the anonymous type's member to be.
否则编译器不知道您希望匿名类型的成员是什么类型。
UpdateAs @AakashM has rightly pointed out - this solves your problem of assigning a null
to an anonymous member - but doesn't actually compile - and if it did it wouldn't allow you to refer to these members.
更新正如@AakashM 正确指出的那样-这解决了您将 a 分配null
给匿名成员的问题-但实际上并没有编译-如果这样做了,它将不允许您引用这些成员。
A fix would be to do this (unfortunately both the null
and the anonymous Planes
array will need casting:
解决方法是这样做(不幸的是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" }
}
}
};
So use IEnumerable
as the member type. You could also use IEnumerable<object>
but the effect will be the same either way.
所以IEnumerable
用作成员类型。您也可以使用,IEnumerable<object>
但无论哪种方式,效果都是一样的。
Or - you could use IEnumerable<dynamic>
as the common type - this would let you do this:
或者 - 您可以将其IEnumerable<dynamic>
用作通用类型 - 这将让您执行以下操作:
Assert.AreEqual("B-52", expected[1].Planes.First().PlaneName);
回答by Viacheslav Ivanov
Just use default(Plane[])
instead of null
.
只需使用default(Plane[])
代替null
.