Ne peut pas affecter null à des anonymes de la propriété de type array
J'ai un tableau de (Pilot
) des objets avec un (Hanger
) de la propriété, qui peut être nulle, ce qui en soi est un (List<Plane>
) propriété. Pour des fins de test, je veux simplifier et "aplatir" ce à un anonyme, un objet avec des propriétés PilotName
(string) et Planes
(array) mais vous ne savez pas comment gérer un null Hanger
un bien ou d'un vide PlanesList
.
(Pourquoi les objets anonymes? Parce que les objets de l'API, j'suis en essais sont en lecture seule et je veux bien le tester pour être "déclarative': autonome, simple et lisible... mais je suis ouvert à d'autres suggestions. Aussi, je vais essayer d'en savoir plus sur LINQ.)
exemple
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));
}
Le problème immédiat est que la ligne expected... Planes = null
erreurs avec,
Ne peut pas attribuer à un type de propriété, mais d'admettre le problème sous-jacent peut-être que l'utilisation
null
dansactual
est à l'aide denull
n'est pas la meilleure approche dans le premier lieu.
Des idées comment faire pour affecter la valeur null tableau dans expected
ou de prendre une approche différente de celle null
dans actual
?
- Le principal problème avec la mise à jour de votre exemple est parce que vous êtes à la vérification de l'égalité entre un agent recenseur (le
WhereSelectArrayIterator
créé par lepilots.Where
appel) et un tableau. Vous pouvez utiliserToArray()
à la fin de laWhere
clause de force dans un tableau. - Le grand problème, je dirais deux choses: d'Abord, Un très bon changement à envisager serait de décisions (par exemple)
Planes
être un vide collection plutôt quenull
, quand il n'y a pas de tous les éléments. Il est beaucoup plus facile à traiter; voici de la lecture de base. Deuxièmement, je pense que vous allez avoir à prendre le contrôle d'égalité entre les résultats réels et les prévisions plus "intelligente", c'est à dire, il va devoir plonger dans les objets et les collections, et d'utiliser quelque chose commeSequenceEqual
. - Vous avez raison, la question maintenant corrigé 🙂
- vide collection: j'ai fait l'arrière-plan de la lecture et je suis d'accord mais je ne peux pas obtenir le changement nécessaire de la droite dans mon code. Pouvez-vous suggérer une solution? Merci. p.s. vous avez raison à propos de l'Assertion trop 🙂
- Hmm, bien sûr, avec parfois
null
Hanger
il est plus difficile... peut-être Null Objet Pattern pour cela. Pour les collections, il suffit de retournerEnumerable.Empty<type>
plutôt quenull
. - J'ai ajouté ma tentative à la fin de la question, mais a une erreur de compilation. Le rclc vous proposer un correctif? Merci encore.
- Avec ça, les deux objets dans le tableau sont en fait différents types, parce que tout
Enumerable.Empty<string>()
etList<string>
à la fois de mettre en œuvreIEnumerable<string>
, ils ne sont pas exactement du même type. Mettre.AsEnumerable()
après lanew List<>()
et il compile - l'a obtenu. Merci encore à tous pour votre aide.
Vous devez vous connecter pour publier un commentaire.
Il y a deux choses qui se passe:
Tout d'abord, lorsque vous créez une instance d'un type anonyme à l'aide de
new { Name = Value}
, afin de construire le type, le compilateur a besoin pour être en mesure de travailler sur la type deValue
. Justenull
sur son propre n'ont pas de type, de sorte que le compilateur ne savez pas quel type de donner à votrePlanes
membre.Maintenant, si vous étiez à l'aide d'un type nommé pour la valeur, vous pouvez simplement dire
(type)null
et être fait, MAIS parce que vous voulez un tableau d'un autre type anonyme, il n'y a aucun moyen de reportez-vous à l'est (c'est anonyme!).Alors, comment obtenez-vous
null
typé en tant que tableau d'un type anonyme? Eh bien, le C# spec garantit que les types anonymes avec les membres les mêmes noms et les types (dans le même ordre!) sont unifiée; qui est, si nous disonspuis
a
etb
ont le même type. Nous pouvons utiliser ce fait pour obtenir notre convenablement tapénull
ainsi:C'est pas joli, mais il fonctionne maintenant
array
a le droit type mais unnull
valeur. Donc, cette compile:new[] { new { PlaneName = "" } }.Take(0).ToArray()
Vous devez utiliser un tapé null:
Ou
Sinon le compilateur n'a aucune idée de quel type que vous voulez l'anonyme de type de membre.
Mise à jour
Comme @AakashM a relevé à juste titre - cela résout votre problème de l'attribution d'une
null
à un membre anonyme - mais n'est pas réellement de la compilation et s'il le fait, il ne serait pas vous permettent de vous référer à ces membres.Une solution serait de le faire (malheureusement les
null
et de l'anonymePlanes
tableau aurez besoin de casting:Donc utiliser
IEnumerable
que le type de membre. Vous pouvez également utiliserIEnumerable<object>
mais l'effet sera le même de toute façon.Ou - vous pouvez utiliser
IEnumerable<dynamic>
comme le type le plus commun - ce qui vous permettrait de faire ceci:IEnumerable
pourrait le faire, mais il ne anéantir tout type de compilation de connaissances.IEnumerable
ne fonctionne - mais nous pouvons corriger le code de test sans changer le code en cours d'essai; voir ma réponse.Suffit d'utiliser
default(Plane[])
au lieu denull
.