Existe uma maneira de retornar o tipo anônimo do método?

Eu sei que não posso escrever um método como:

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

Eu posso fazer de outra forma:

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

mas eu não quero fazer a segunda opção porque, se eu fizer isso, terei que usar a reflection.


Por que eu quero fazer isso:

Hoje eu tenho um método dentro da minha página aspx que retorna um datatable como resultado e não posso alterá-lo , eu estava tentando converter este DataTable para um método anônimo com as propriedades que eu quero trabalhar. Eu não queria criar uma class apenas para fazer isso e como vou precisar realizar a mesma consulta mais de uma vez, pensei em criar um método que retorna um tipo anônimo seria uma boa ideia.

Retornando como um System.Object é a única maneira de retornar um tipo anônimo de um método. Infelizmente, não há outra maneira de fazer isso, pois os tipos anônimos foram projetados especificamente para impedir seu uso dessa maneira.

Existem alguns truques que você pode fazer em conjunto com o retorno de um Object que permite chegar perto. Se você estiver interessado nesta solução, por favor leia Não é possível retornar o tipo anônimo do método? Mesmo? .

Aviso: Mesmo que o artigo que eu criei mostre uma solução alternativa que não signifique que seja uma boa ideia fazê-lo. Eu seria fortemente desencorajar você usando essa abordagem ao criar um tipo regular seria mais seguro e mais fácil de entender.

Como alternativa, você pode usar a class Tuple no .NET 4.0 e superior:

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

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

então você pode acessar as propriedades assim:

 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; } 

A solução mais fácil é criar uma class, inserir os valores na propriedade e, em seguida, retorná-la. Se tipos anônimos estiverem dificultando sua vida, você não os usará corretamente.

Não obstante os avisos sobre se esta é uma boa idéia ou não … Uma dynamic parece funcionar muito bem para um método privado.

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

Você pode executar este exemplo no LinqPad. Isso irá produzir:

Resultado: test1, test2

Como alternativa, a partir de C # 7, podemos usar ValueTuple . Um pequeno exemplo daqui :

 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; } 

E no fim de recepção:

 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}"); 

Eu acho que Andrew Hare está certo, você teria que apenas retornar “object”. Para um comentário editorial, sinto que lidar com objects brutos no código OO pode ser um “cheiro de código”. Há casos em que é a coisa certa a se fazer, mas na maioria das vezes, seria melhor definir uma interface para retornar ou usar algum tipo de class base, se você retornasse os tipos relacionados.

Não, os tipos anônimos não podem existir fora do contexto em que são criados e, como resultado, não podem ser usados ​​como um tipo de retorno de método. Você pode retornar a instância como um object , mas é muito melhor criar explicitamente seu próprio tipo de contêiner para essa finalidade.

Desculpe, você realmente não deveria fazer isso. Você pode contorná-lo com reflection ou fazendo um método auxiliar genérico para retornar o tipo para você, mas isso está realmente trabalhando contra a linguagem. Apenas declare o tipo, então está claro o que está acontecendo.

Não, não há suporte para expandir o escopo da class anônima fora do método. Fora do método, a class é realmente anônima, e a reflection é a única maneira de acessar seus membros.

Você também pode inverter o stream de controle, se possível:

  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(); } 

e depois mais tarde em outro lugar:

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