Anonymous type return in C #

I have a request that returns an anonymous type, and the request is in a method. How do you write this:

public "TheAnonymousType" TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return "TheAnonymousType"; } } 
+82
c # anonymous-types return-type
Apr 09 2018-12-12T00:
source share
15 answers

You can not.

You can only return an object or a container of objects, for example. IEnumerable<object> , IList<object> , etc.

+79
Apr 09 2018-12-12T00:
source share

You can return dynamic , which will give you a verified version of the anonymous type, but only in .NET 4+

+36
Apr 09 2018-12-12T00:
source share

You cannot return anonymous types. Can you create a model that can be returned? Otherwise, you must use object .

Here is an article written by John Skeet on this subject.

Code from the article:

 using System; static class GrottyHacks { internal static T Cast<T>(object target, T example) { return (T) target; } } class CheesecakeFactory { static object CreateCheesecake() { return new { Fruit="Strawberry", Topping="Chocolate" }; } static void Main() { object weaklyTyped = CreateCheesecake(); var stronglyTyped = GrottyHacks.Cast(weaklyTyped, new { Fruit="", Topping="" }); Console.WriteLine("Cheesecake: {0} ({1})", stronglyTyped.Fruit, stronglyTyped.Topping); } } 

Or here is another similar article

Or as others comment, you can use dynamic

+25
Apr 09 2018-12-12T00:
source share

In C # 7, we can use tuples to achieve this:

 public List<(int SomeVariable, string AnotherVariable)> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB .Select(s => ( SomeVariable = s.SomeVariable, AnotherVariable = s.AnotherVariable)) .ToList(); } } 

You may need to install the nuget System.ValueTuple package.

+18
Mar 29 '17 at 7:46
source share

You can use the Tuple class as a replacement for anonymous types if you need to return:

Note. A tuple can contain up to 8 parameters.

 return Tuple.Create(variable1, variable2); 

Or, for example, from the original message:

 public List<Tuple<SomeType, AnotherType>> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select Tuple.Create(..., ...) ).ToList(); return TheQueryFromDB.ToList(); } } 

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

+17
Jul 02 '14 at 16:55
source share

The C # compiler is a two-phase compiler. In the first step, it simply checks for namespaces, class hierarchies, method signatures, etc. The organs of the methods are compiled only during the second phase.

Anonymous types are not defined until the body of the method is compiled.

Thus, the compiler has no way to determine the return type of the method during the first phase.

This is why anonymous types cannot be used as return types.

Like others, if you use .net 4.0 or ter, you can use Dynamic .

If I were you, I would probably create a type and return that type from the method. Thus, it is easy for future programmers to save their code and read it.

+9
Apr 09 2018-12-12T00:
source share

Three options:

Option1:

 public class TheRepresentativeType { public ... SomeVariable {get;set;} public ... AnotherVariable {get;set;} } public IEnumerable<TheRepresentativeType> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; } } 

Option 2:

 public IEnumerable TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; } } 

you can repeat it as an object

Option 3:

 public IEnumerable<dynamic> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new TheRepresentativeType{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB; //You may need to call .Cast<dynamic>(), but I'm not sure } } 

and you can iterate over it as a dynamic object and directly access your properties.

+8
Apr 09 2018-12-12T00:
source share

In this case, you can return a list of objects.

 public List<object> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new { SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB ; } } 
+2
Apr 09 2018-12-12T00:
source share
 public List<SomeClass> TheMethod(SomeParameter) { using (MyDC TheDC = new MyDC()) { var TheQueryFromDB = (.... select new SomeClass{ SomeVariable = ...., AnotherVariable = ....} ).ToList(); return TheQueryFromDB.ToList(); } } public class SomeClass{ public string SomeVariable{get;set} public string AnotherVariable{get;set;} } 

Creating my own class and queries for it is the best solution I know. As far as I know, you cannot use anonymous type values ​​to return in another method, because it will not just be recognized. However, they can be used in the same method. I used them as IQueryable or IEnumerable , although it still does not allow you to see what is inside the variable of an anonymous type.

I came across something similar before, while I was trying to reorganize some kind of code, you can check it here: Refactoring and creating separate methods

+2
Apr 09 2018-12-12T00:
source share

Using C # 7.0, we still cannot return anonymous types, but we do have tuple type support , and thus we can return the tuple collection ( System.ValueTuple<T1,T2> in this case).

The shortest version of the code you want might look like this:

 public List<(int SomeVariable, object AnotherVariable)> TheMethod() { ... return (from data in TheDC.Data select (SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject) ).ToList(); } 

Or using the free Linq syntax:

 return TheDC.Data .Select(data => (SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject)) .ToList(); 

Using C # 7.1, we can omit the tuple's property names and they will be inferred from the initialization of the tuple, as it works with anonymous types:

 select (data.SomeInt, data.SomeObject) // or Select(data => (data.SomeInt, data.SomeObject)) 
+2
Nov 16 '18 at 15:29
source share

With reflection.

 public object tst() { var a = new { prop1 = "test1", prop2 = "test2" }; return a; } public string tst2(object anonymousObject, string propName) { return anonymousObject.GetType().GetProperties() .Where(w => w.Name == propName) .Select(s => s.GetValue(anonymousObject)) .FirstOrDefault().ToString(); } 

Sample:

 object a = tst(); var val = tst2(a, "prop2"); 

Exit:

 test2 
+2
Dec 19 '18 at 9:12
source share

You can only use a dynamic keyword,

  dynamic obj = GetAnonymousType(); Console.WriteLine(obj.Name); Console.WriteLine(obj.LastName); Console.WriteLine(obj.Age); public static dynamic GetAnonymousType() { return new { Name = "John", LastName = "Smith", Age=42}; } 

But with a dynamic type keyword, you lose compile-time security, IntelliSense IDEs, etc.

0
Apr 01 '18 at 11:44
source share

Another option would be to use automapper: you will convert to any type from your anonymous return object if long public properties match. The key points that return an object are linq and autommaper. (or use a similar idea returning serialized JSON etc., or use reflection ...)

 using System.Linq; using System.Reflection; using AutoMapper; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; namespace UnitTestProject1 { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { var data = GetData(); var firts = data.First(); var info = firts.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public).First(p => p.Name == "Name"); var value = info.GetValue(firts); Assert.AreEqual(value, "One"); } [TestMethod] public void TestMethod2() { var data = GetData(); var config = new MapperConfiguration(cfg => cfg.CreateMissingTypeMaps = true); var mapper = config.CreateMapper(); var users = data.Select(mapper.Map<User>).ToArray(); var firts = users.First(); Assert.AreEqual(firts.Name, "One"); } [TestMethod] public void TestMethod3() { var data = GetJData(); var users = JsonConvert.DeserializeObject<User[]>(data); var firts = users.First(); Assert.AreEqual(firts.Name, "One"); } private object[] GetData() { return new[] { new { Id = 1, Name = "One" }, new { Id = 2, Name = "Two" } }; } private string GetJData() { return JsonConvert.SerializeObject(new []{ new { Id = 1, Name = "One" }, new { Id = 2, Name = "Two" } }, Formatting.None); } public class User { public int Id { get; set; } public string Name { get; set; } } } } 
0
Oct. 15 '18 at 0:21
source share

Especially with local functions, but you can always do this by passing in a delegate that creates an anonymous type.

So if your goal was to run another logic in the same sources and be able to combine the results in one list. I'm not sure what the nuance of this is not enough to achieve the goal, but as long as you return T and pass the delegate to create T , you can return an anonymous type from the function.

 // returning an anonymous type // look mom no casting void LookMyChildReturnsAnAnonICanConsume() { // if C# had first class functions you could do // var anonyFunc = (name:string,id:int) => new {Name=name,Id=id}; var items = new[] { new { Item1 = "hello", Item2 = 3 } }; var itemsProjection =items.Select(x => SomeLogic(x.Item1, x.Item2, (y, i) => new { Word = y, Count = i} )); // same projection = same type var otherSourceProjection = SomeOtherSource((y,i) => new {Word=y,Count=i}); var q = from anony1 in itemsProjection join anony2 in otherSourceProjection on anony1.Word equals anony2.Word select new {anony1.Word,Source1Count=anony1.Count,Source2Count=anony2.Count}; var togetherForever = itemsProjection.Concat(otherSourceProjection).ToList(); } T SomeLogic<T>(string item1, int item2, Func<string,int,T> f){ return f(item1,item2); } IEnumerable<T> SomeOtherSource<T>(Func<string,int,T> f){ var dbValues = new []{Tuple.Create("hello",1), Tuple.Create("bye",2)}; foreach(var x in dbValues) yield return f(x.Item1,x.Item2); } 
0
Feb 11 '19 at 14:40
source share

This is another example of crazy C # developers.

0
Jun 08 '19 at 12:44 on
source share



All Articles