Linq - Casting IQueryable à IList retourne null - POURQUOI?
Je manque quelque chose d'évident ici. Je ne comprends pas pourquoi cette distribution des résultats d'une requête linq retourne null et non pas la liste tapée je suis requérant.
IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
Le code complet pour l'exécuter ce qui est ci-dessous. C'est une lacune des connaissances, j'ai besoin de pont. J'ai essayé toutes sortes de permutations de jette pour le faire fonctionner. Je n'ai pas d'Exceptions, juste une valeur null. Il convient de noter que la requête Linq est la sélection de ses résultats dans les instances de mon custom "MyDataClass", qui met en œuvre IMyDataInterface
class Program
{
static void Main(string[] args)
{
IMyFunctionalInterface myObject = new MyClass();
//myObject.Get() returns null for some reason...
IList<IMyDataInterface> list = myObject.Get();
Debug.Assert(list != null, "Cast List is null");
}
}
public interface IMyFunctionalInterface
{
IList<IMyDataInterface> Get();
}
public class MyClass : IMyFunctionalInterface
{
public IList<IMyDataInterface> Get()
{
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
var query = from n in names
where n.Contains("a")
select new MyDataClass
{
Name = n.ToString()
};
//There IS data in the query result
Debug.Assert(query != null, "result is null");
//but the cast here makes it return null
IList<IMyDataInterface> list = query.ToList() as IList<IMyDataInterface>;
return list;
}
}
public interface IMyDataInterface
{
string Name { get; set; }
}
public class MyDataClass : IMyDataInterface
{
public string Name { get; set; }
}
Ce qui se passe quand vous venez de supprimer la sécurité cast ("comme IList<IMyDataInterface>")? Je pense que vous pourriez juste l'exécuter .ToList() et de le coller dans votre IList<IMyDataInterface> variable.
Je pensais que trop, mais il ne fonctionne pas.
Je pensais que trop, mais il ne fonctionne pas.
OriginalL'auteur jlembke | 2009-01-30
Vous devez vous connecter pour publier un commentaire.
Le problème ici, c'est l'un des covariance.
Tout d'abord, votre exemple est un peu trop compliqué. J'ai enlevé un peu de duvet. Aussi, j'ai ajouté des diagnostics d'éclairer le problème.
La sortie de ce programme est:
Noter que nous sommes en train de jeter un
List<C>
àList<I>
qui ne fonctionne pas en C# 3.0.En C# 4.0, vous devez être capable de faire cela, grâce à la nouvelle co - et contra-variance des paramètres de type générique interfaces.
Aussi, l'original de votre question posée sur l'
IQueryable
mais ce n'est pas pertinente en l'espèce: l'expression de la requête que vous avez fourni crée unIEnumerable<string>
pas unIQueryable<string>
.MODIFIER: je tiens à souligner que votre "cast" à l'aide de la
as
opérateur n'est techniquement pas un plâtre, mais est un "type de conversion". Si vous deviez utiliser un cast, vous auriez eu droit à une exception avec des informations utiles. Si je change d':- Je obtenir une
InvalidCastException
avec:Notez qu'en C# 4.0 covariance/contravariance ne s'applique qu'aux délégués et d'interfaces, de sorte que la distribution de la Liste des<C> Liste<I> en C# 4.0 ne fonctionne pas, soit, et c'est tout.
Je ne suis pas sûr de comprendre cette réponse. Si le type de conversion / cast en C# 4.0? (Note: j'ai l'InvalidCastException même si je suis à l'aide de C# 4.0.)
(J'ai été absent à partir de C# pour un certain temps, donc je suis un peu floue.) C# 4.0 ajoute le co - et contra-variance pour l'interface des paramètres de type. Le NPD annoté quelques interfaces pour co-et contra-variance. Par exemple, dans mon Beta 2 build, je vois que
IEnumerable
est maintenantout T
, maisIList
ne l'est pas. Ainsi, dans le code ci-dessus, je peux écrirequery.ToList() as IEnumerable<I>
et il fonctionne (non-nulle).OriginalL'auteur Jay Bazuzi
Essayez ceci:
Votre problème, c'est cette ligne:
Cela peut aussi être écrit comme:
Malheureusement, en C# le
as
opérateur ne fonctionne pas dans la façon dont vous le souhaitez. Leas
opérateur rejette simplement l'objet de liste, comme une liste d'un type différent; il ne tente pas de passer par la liste et de la fonte de chaque élément. Pour lancer une liste de quelque chose d'autre, vous devez appeler le Casting de la méthode d'extension sur elle. E. g.:Vos options sont les suivantes: cast jamais élément dans votre requête, comme l'interface que vous souhaitez (mon premier exemple) ou en fonte de la totalité de la liste après que vous avez exécuté votre requête (mon deuxième exemple).
Je suggère l'ancien.
Je l'ai testé avant que j'ai posté. La distribution des œuvres dans l'approche 1, car la partie select peut prendre n'importe quelle valide C# construction de l'expression.
OriginalL'auteur Randolpho