ajoutez d'Action générique<T> délègue à une liste
Est-il possible d'ajouter un générique délégué à l'Action pour une Liste de la collection?
J'ai besoin d'une sorte de simple système de messagerie pour une application Silverlight.
Mise à JOUR
Ce qui suit est ce que j'ai vraiment "envie"
class SomeClass<T>
{
public T Data { get; set; }
//and more ....
}
class App
{
List<Action<SomeClass<T>>> _actions = new List<Action<SomeClass<T>>>();
void Add<T>( Action<SomeClass<T>> foo )
{
_actions.Add( foo );
}
}
Compilateur:
The type or namespace name 'T' could not be found (are you missing a using directive or an assembly reference?)
code initial ciselée
classe SomeClassBase
{ }
class SomeClass<T> : SomeClassBase
{
public T Data { get; set; }
//and more ....
}
class App
{
List<Action<SomeClassBase>> _actions = new List<Action<SomeClassBase>>();
void Add<T>( Action<SomeClass<T>> foo )
where T : SomeClassBase
{
_actions.Add( foo );
}
}
Le compilateur se plaint - pour la _actions.Ajouter ();
Argument 1: cannot convert from 'System.Action<test.SomeClass<T>>' to 'System.Action<test.SomeClassBase>'
The best overloaded method match for 'System.Collections.Generic.List<System.Action<test.SomeClassBase>>.Add(System.Action<test.SomeClassBase>)' has some invalid arguments
De l'application côté il n'est pas nécessaire pour le SomeClassBase classe, pourtant, il semble impossible de définir une Liste de Action<SomeClass<T>>
éléments et l'approche avec la classe de base de travaux lors de l'utilisation de la classe dans la Liste, au lieu de l'Action
Grâce,
jochen
"il semble impossible de définir une Liste d'Action<SomeClass<T>>" - voulez-vous votre liste de contenir des actions avec plus d'un type
pas de tous les éléments de la liste ont le même type de T, mais je pourrais avoir un autre membre de la Liste avec un deuxième type
T
?pas de tous les éléments de la liste ont le même type de T, mais je pourrais avoir un autre membre de la Liste avec un deuxième type
OriginalL'auteur jochen | 2010-07-23
Vous devez vous connecter pour publier un commentaire.
EDIT: Ok, maintenant je vois ce que vous essayez de faire. J'ai laissé l'ancien réponse ci-dessous pour la postérité 🙂
Malheureusement, vous ne pouvez pas exprimer la relation que vous voulez en C# les génériques, mais comme vous pouvez assurez-vous que vous êtes le seul de la manipulation de la collection, vous pouvez le conserver en lieu sûr vous-même:
Essayez ceci:
Notez que vous pourrait utiliser le fait que les délégués sont multicast pour simplement garder une
Dictionary<Type, Delegate>
et de les combiner ensemble, mais je vais laisser ça comme un exercice pour le lecteur 🙂Vieille réponse
C'est l'échec pour une bonne raison. Débarrassons-nous de l'génériques (comme ils sont hors de propos ici) et de réfléchir à un cas plus simple - les fruits et les bananes.
Vous essayez d'ajouter un
Action<Banana>
à unList<Action<Fruit>>
. Vous ne pouvez pas le faire, même avec le générique de la variance de C# 4. Pourquoi? Parce qu'il n'est pas sûr. Considérez ceci:Eek! Maintenant, nous avons une banane éplucheur à essayer de peler une fraise... quel gâchis!
Pas que le autres chemin de ronde, serait acceptable en C# 4:
Ici, nous allons ajouter un
Action<Fruit>
à unList<Action<Banana>>
- ce qui est acceptable, parce que tout ce que vous pouvez faire pour unAction<Banana>
est également valable pour unAction<Fruit>
.D'accord, je suis avec vous. Le montage.
Vous devrez peut-être aller dynamiques. Utiliser un
Dictionary<Type, List<Delegate>>
, etDelegate.DynamicInvoke
d'invoquer les délégués.Merci! votre dernier code est exactement la façon dont je veux qu'il fonctionne. Je vais essayer de trouver la solution de multidiffusion.
une petite faute de frappe tmp = new List<Délégué>(); devrait plutôt être tmp = new List<<SomeClass<T>>(); else nous obtenons InvalidCast exceptions
OriginalL'auteur Jon Skeet
Cela fera ce que vous voulez?
Cela fonctionne parce que vous êtes la création d'un léger fonction anonyme qui reporte à l'foo paramètre, mais jette l'argument que le type, le compilateur veut.
OriginalL'auteur Brian Genisio
Ne sais pas si c'est ce que vous voulez. Mais essayez de vous changer de méthode Add:
Mise à jour
Cela vous permettra de faire quelque chose comme ceci:
OriginalL'auteur Martin Ingvar Kofoed Jensen
OriginalL'auteur EXAMPLE
Si vous regardez la ligne
La classe T que vous faites référence n'a pas été déclaré, n'importe où. Dans SomeClass vous avez le droit de déclaration pour une classe générique, mais dans votre classe App vous n'avez pas dit que T est dans ce cas particulier.
En résumé, je ne pense pas que c'est de faire ce que vous souhaitez. Avec les génériques de ses plus facile d'imaginer que, lorsque le code a été compilé il n'y a pas une telle chose comme les génériques[0]. Que lors de la compilation de ses vient de rendre toutes les classes que vous êtes en utilisant de façon générique. Cela signifie qu'il n'est pas vraiment un concept d'une liste de classes génériques depuis le temps que vous les utilisez, les classes sont d'un type donné et ne peut donc pas être mélangés.
Je pense que la façon dont il aurait besoin pour le travail est plus précis à l'aide de définitions de classe, mais comme Jon Skeet a expliqué que ne fonctionne pas vraiment.
Peut-être la meilleure idée est de prendre un peu de régressions et de poser une question sur ce que vous faites avec ce système de messagerie?
[0] Génériques fonctionnent différemment dans différentes langues, mais c'est un bon rugueux principe de travailler sur je pense...
OriginalL'auteur Chris
Je ne sais pas si c'est ce que vous voulez exactement, mais si vous voulez avoir une méthode qui invoque une action pour chaque élément dans une liste, vous pouvez utiliser une méthode d'extension comme ça :
Un exemple d'appel à myList de type
IEnumerable<string>
:Peut-être LINQ déjà met en œuvre une action dans une Liste, mais si c'est le cas, je ne connais pas la syntaxe.
OriginalL'auteur Axel