Existe-t-il un moyen de renvoyer le type anonyme de la méthode?

Je sais que je ne peux pas écrire une méthode comme:

public var MyMethod() { return new{ Property1 = "test", Property2="test"}; } 

Je peux le faire autrement:

 public object MyMethod() { return new{ Property1 = "test", Property2="test"} } 

mais je ne veux pas faire la deuxième option car si je le fais, je devrai utiliser la reflection.


Pourquoi je veux faire ça:

Aujourd’hui, j’ai une méthode dans ma page aspx qui renvoie un résultat pouvant être daté et je ne peux pas le changer , j’essayais de convertir ce DataTable en une méthode anonyme avec les propriétés avec lesquelles je veux travailler. Je ne voulais pas créer une classe uniquement pour faire cela et comme je devrai effectuer la même requête plus d’une fois, je pensais que créer une méthode qui renvoie un type anonyme serait une bonne idée.

Le System.Object tant que System.Object est le seul moyen de renvoyer un type anonyme à partir d’une méthode. Malheureusement, il n’ya pas d’autre moyen de le faire car les types anonymes ont été conçus spécifiquement pour empêcher leur utilisation de cette manière.

Il y a quelques astuces que vous pouvez faire pour renvoyer un Object qui vous permet de vous rapprocher. Si vous êtes intéressé par cette solution de contournement, veuillez lire Impossible de renvoyer le type anonyme de la méthode? Vraiment? .

Disclaimer: Même si l’article que j’ai lié montre une solution de contournement, cela ne signifie pas que c’est une bonne idée de le faire. Je vous découragerais fortement d’utiliser cette approche lorsque la création d’un type régulier serait plus sûre et plus facile à comprendre.

Vous pouvez également utiliser la classe Tuple dans .NET 4.0 et versions ultérieures:

http://msdn.microsoft.com/en-us/library/system.tuple(v=vs.110).aspx

 Tuple Create() { return Tuple.Create("test1", "test2"); } 

alors vous pouvez accéder aux propriétés comme ceci:

 var result = Create(); result.Item1; result.Item2; 
 public object MyMethod() { return new { Property1 = "test", Property2 = "test" }; } static void Main(..) { dynamic o = MyMethod(); var p1 = o.Property1; var p2 = o.Property2; } 

La solution la plus simple consiste à créer une classe, à insérer les valeurs dans la propriété, puis à la renvoyer. Si les types anonymes rendent votre vie plus difficile, vous ne les utilisez pas correctement.

En dépit des avertissements sur le fait de savoir si c’est une bonne idée ou non … Une dynamic semble fonctionner correctement pour une méthode privée.

 void Main() { var result = MyMethod(); Console.WriteLine($"Result: {result.Property1}, {result.Property2}"); } public dynamic MyMethod() { return new { Property1 = "test1", Property2 = "test2" }; } 

Vous pouvez exécuter cet exemple dans LinqPad. Il va sortir:

Résultat: test1, test2

Comme alternative, à partir de C # 7, nous pouvons utiliser ValueTuple . Un petit exemple d’ ici :

 public (int sum, int count) DoStuff(IEnumerable values) { var res = (sum: 0, count: 0); foreach (var value in values) { res.sum += value; res.count++; } return res; } 

Et à la réception:

 var result = DoStuff(Enumerable.Range(0, 10)); Console.WriteLine($"Sum: {result.Sum}, Count: {result.Count}"); 

Ou:

 var (sum, count) = DoStuff(Enumerable.Range(0, 10)); Console.WriteLine($"Sum: {sum}, Count: {count}"); 

Je pense qu’Andrew Hare a raison, il vous suffit de retourner “object”. Pour un commentaire éditorial, j’ai le sentiment que traiter des objects bruts en code OO peut être une “odeur de code”. Il y a des cas où c’est la bonne chose à faire, mais la plupart du temps, il serait préférable de définir une interface pour renvoyer, ou d’utiliser un type de classe de base, si vous voulez renvoyer des types associés.

Non, les types anonymes ne peuvent exister en dehors du contexte dans lequel ils sont créés et ne peuvent donc pas être utilisés comme type de retour de méthode. Vous pouvez renvoyer l’instance en tant object , mais il est préférable de créer explicitement votre propre type de conteneur à cette fin.

Désolé, vous n’êtes vraiment pas censé faire ça. Vous pouvez le contourner par reflection ou en créant une méthode d’assistance générique pour renvoyer le type pour vous, mais cela fonctionne vraiment contre le langage. Déclarez simplement le type afin qu’il soit clair ce qui se passe.

Non, l’extension de la classe anonyme en dehors de la méthode n’est pas prise en charge. En dehors de la méthode, la classe est vraiment anonyme et la reflection est le seul moyen d’accéder à ses membres.

Vous pouvez également inverser votre stream de contrôle si possible:

  public abstract class SafeAnon { public static Anon Create(Func anonFactory) { return new Anon(anonFactory()); } public abstract void Fire(TContext context); public class Anon : SafeAnon { private readonly T _out; public delegate void Delayed(TContext context, T anon); public Anon(T @out) { _out = @out; } public event Delayed UseMe; public override void Fire(TContext context) { UseMe?.Invoke(context, _out); } } } public static SafeAnon Test() { var sa = SafeAnon.Create(() => new { AnonStuff = "asdf123" }); sa.UseMe += (ctx, anon) => { ctx.Stuff.Add(anon.AnonStuff); }; return sa; } public class SomeContext { public List Stuff = new List(); } 

et puis plus tard ailleurs:

  static void Main() { var anonWithoutContext = Test(); var nowTheresMyContext = new SomeContext(); anonWithoutContext.Fire(nowTheresMyContext); Console.WriteLine(nowTheresMyContext.Stuff[0]); }