(Pilot
)プロパティを持つ(Hanger
)オブジェクトの配列があり、それはnullである可能性があり、それ自体に(List<Plane>
)プロパティ。テストのために、これを単純化して、プロパティPilotName
(string)およびPlanes
(array)を持つ匿名オブジェクトに「フラット化」したいが、null Hanger
プロパティまたは空のPlanesList
。
(なぜ匿名オブジェクトなのですか?私がテストしているAPIのオブジェクトは読み取り専用であり、テストを「宣言的」にしたいので、自己完結型でシンプルで読み取り可能です...しかし、他の提案にもオープンです。 m 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));
}
当面の問題は、行expected... Planes = null
エラー、
匿名タイプのプロパティに割り当てることはできませんが、根本的な問題は
null
でactual
を使用することはnull
を使用することが最初から最善のアプローチではないことを認めています。
expected
のnull配列を割り当てる方法、またはnull
のactual
とは異なるアプローチを取る方法はありますか?
発生していることが2つあります。
まず、new { Name = Value}
を使用して匿名型のインスタンスを構築する場合、型を構築するには、コンパイラがValue
の-typeを計算できる必要があります。 null
自体には型がないので、コンパイラーはPlanes
メンバーにどの型を与えるかわかりません。
値に名前付きの型を使用している場合、(type)null
と言うだけで完了しますが、別の匿名型の配列が必要なため、する方法はありません。への参照is(それは匿名です!).
それでは、匿名型の配列としてnull
をどのように入力しますか?まあ、C#仕様では、同じ名前と型(同じ順序で!)のメンバーを持つ匿名型がnifiedであることを保証しています。つまり、
var a = new { Foo = "Bar" };
var b = new { Foo = "Baz" };
次に、a
とb
には同じタイプがあります。この事実を使用して、適切に型付けされたnull
を取得できます。
var array = (new[] { new { PlaneName = "" } });
array = null;
それはきれいではありませんが、動作します-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" }
}
}
};
typednullを使用する必要があります:
(List<Plane>)null
または
(Plane[])null
それ以外の場合、コンパイラーは、匿名型のメンバーにしたい型を認識しません。
pdate @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" }
}
}
};
したがって、メンバータイプとしてIEnumerable
を使用します。 IEnumerable<object>
を使用することもできますが、効果はどちらの方法でも同じです。
または-IEnumerable<dynamic>
を一般的なタイプとして使用できます-これによりこれを行うことができます:
Assert.AreEqual("B-52", expected[1].Planes.First().PlaneName);
null
の代わりにdefault(Plane[])
を使用してください。