35

Pilot()プロパティを持つ()オブジェクトの配列がHangerあります。これはnullの場合があり、それ自体が(List<Plane>)プロパティを持っています。テストの目的で、これを単純化して、プロパティPilotName(string)とPlanes(array)を持つ匿名オブジェクトに「フラット化」したいのですが、nullHangerプロパティまたは空のプロパティを処理する方法がわかりません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エラーです。

匿名タイプのプロパティに割り当てることはできませんが、根本的な問題は、nullinactualを使用することnullがそもそも最善のアプローチではないことである可能性があることを認めます。

でnull配列を割り当てる方法、またはでexpectedとは異なるアプローチを取る方法についてのアイデアnullはありますactualか?

4

3 に答える 3

73

型付き nullを使用する必要があります:

(List<Plane>)null

または

(Plane[])null

そうしないと、コンパイラは匿名型のメンバーをどの型にするかわかりません。

@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);
于 2013-01-14T10:58:48.993 に答える
41

起こっていることが2つあります:

まず、を使用して匿名型のインスタンスを作成する場合、型を作成するには、コンパイラが。のnew { Name = Value}処理できる必要があります。それ自体には型がないため、コンパイラはメンバーにどの型を与えるかを知りません。ValuenullPlanes

さて、値に名前付き型を使用している場合は、言うだけ(type)nullで完了できますが、別の匿名型の配列が必要なため、isを参照する方法はありません(匿名です!)。

では、どのようにしnullて匿名型の配列として型付けされるのでしょうか?C#仕様では、メンバーが同じ名前とタイプ(同じ順序で!)の匿名タイプが統一されていることが保証されています。つまり、私たちが言うなら

var a = new { Foo = "Bar" };
var b = new { Foo = "Baz" };

次に、同じタイプab持ちます。この事実を使用して、適切に型指定されたものを取得できます。null

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

きれいではありませんが、機能します。現在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"
      }
    }
  }
};
于 2013-01-14T11:13:39.177 に答える
13

default(Plane[])の代わりに使用してnullください。

于 2013-01-14T11:01:19.510 に答える