Returning anonymous type in C#

C#.NetAnonymous TypesReturn Type

C# Problem Overview


I have a query that returns an anonymous type and the query 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";
    }
}

C# Solutions


Solution 1 - C#

You can't.

You can only return object, or container of objects, e.g. IEnumerable<object>, IList<object>, etc.

Solution 2 - C#

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

Solution 3 - C#

In C# 7 we can use tuples to accomplish 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 might need to install System.ValueTuple nuget package though.

Solution 4 - C#

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

Here is an article written by Jon Skeet on the 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 are commenting, you could use dynamic

Solution 5 - C#

You can use the Tuple class as a substitute for an anonymous types when returning is necessary:

Note: Tuple can have up to 8 parameters.

return Tuple.Create(variable1, variable2);

Or, for the example from the original post:

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

Solution 6 - C#

C# compiler is a two phase compiler. In the first phase it just checks namespaces, class hierarchies, Method signatures etc. Method bodies are compiled only during the second phase.

Anonymous types are not determined until the method body is compiled.

So the compiler has no way of determining the return type of the method during the first phase.

That is the reason why anonymous types can not be used as return type.

As others have suggested if you are using .net 4.0 or grater, you can use Dynamic.

If I were you I would probably create a type and return that type from the method. That way it is easy for the future programmers who maintains your code and more readable.

Solution 7 - C#

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 iterate it as 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 will be able to iterate it as a dynamic object and access their properties directly

Solution 8 - C#

Using C# 7.0 we still can't return anonymous types but we have a support of tuple types and thus we can return a collection of tuple (System.ValueTuple<T1,T2> in this case). Currently Tuple types are not supported in expression trees and you need to load data into memory.

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

public IEnumerable<(int SomeVariable, object AnotherVariable)> TheMethod()
{
	...

    return (from data in TheDC.Data
		select new { data.SomeInt, data.SomeObject }).ToList()
		.Select(data => (SomeVariable: data.SomeInt, AnotherVariable: data.SomeObject))
}

Or using the fluent Linq syntax:

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

Using C# 7.1 we can omit properties names of tuple and they will be inferred from tuple initialization like it works with anonymous types:

select (data.SomeInt, data.SomeObject)
// or
Select(data => (data.SomeInt, data.SomeObject))

Solution 9 - C#

You can return list of objects in this case.

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

      return TheQueryFromDB ;
    }
}

Solution 10 - C#

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 your own class and querying for it is the best solution I know.As much as I know you can not use anonymous type return values in another method, because it won't just be recognized.However, they can be used in the same method. I used to return them as IQueryable or IEnumerable, though it still does not let you see what is inside of the anonymous type variable.

I run into something like this before while I was trying to refactor some code, you can check it here : Refactoring and creating separate methods

Solution 11 - C#

You can only use 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 dynamic type keyword you will loose compile time safety, IDE IntelliSense etc...

Solution 12 - C#

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

Output:

test2

Solution 13 - C#

It is actually possible to return an anonymous type from a method in a particular use-case. Let's have a look!

With C# 7 it is possible to return anonymous types from a method, although it comes with a slight constraint. We are going to use a new language feature called local function together with an indirection trick (another layer of indirection can solve any programming challenge, right?).

Here's a use-case I recently identified. I want to log all configuration values after I have loaded them from AppSettings. Why? Because there's some logic around missing values that revert to default values, some parsing and so on. An easy way to log the values after applying the logic is to put them all in a class and serialize it to a logfile (using log4net). I also want to encapsulate the complex logic of dealing with settings and separate that from whatever I need to do with them. All without creating a named class that exists just for a single use!

Let's see how to solve this using a local function that creates an anonymous type.

public static HttpClient CreateHttpClient()
{
    // I deal with configuration values in this slightly convoluted way.
    // The benefit is encapsulation of logic and we do not need to
    // create a class, as we can use an anonymous class.
    // The result resembles an expression statement that
    // returns a value (similar to expressions in F#)
    var config = Invoke(() =>
    {
        // slightly complex logic with default value
        // in case of missing configuration value
        // (this is what I want to encapsulate)
        int? acquireTokenTimeoutSeconds = null;
        if (int.TryParse(ConfigurationManager.AppSettings["AcquireTokenTimeoutSeconds"], out int i))
        {
            acquireTokenTimeoutSeconds = i;
        }

        // more complex logic surrounding configuration values ...

        // construct the aggregate configuration class as an anonymous type!
        var c = new
        {
            AcquireTokenTimeoutSeconds =
                acquireTokenTimeoutSeconds ?? DefaultAcquireTokenTimeoutSeconds,
            // ... more properties
        };

        // log the whole object for monitoring purposes
        // (this is also a reason I want encapsulation)
        Log.InfoFormat("Config={0}", c);
        return c;
    });

    // use this configuration in any way necessary...
    // the rest of the method concerns only the factory,
    // i.e. creating the HttpClient with whatever configuration
    // in my case this:
    return new HttpClient(...);

    // local function that enables the above expression
    T Invoke<T>(Func<T> func) => func.Invoke();
}

I have succeeded in constructing an anonymous class and also encapsulated the logic of dealing with complex settings management, all inside CreateHttpClient and within its own "expression". This might not be exactly what the OP wanted but it is a lightweight approach with anonymous types that is currently possible in modern C#.

Solution 14 - C#

Another option could be using automapper: You will be converting to any type from your anonymous returned object as long public properties matches. The key points are, returning object, use linq and autommaper. (or use 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; }
        }
    }

}

Solution 15 - C#

Now with local functions especially, but you could always do it by passing a delegate that makes the anonymous type.

So if your goal was to run different logic on the same sources, and be able to combine the results into a single list. Not sure what nuance this is missing to meet the stated goal, but as long as you return a T and pass a delegate to make T, you can return an anonymous type from a 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);
}

Solution 16 - C#

I am not sure of the name of this construct, I thought this was called an anonymous type but I might be wrong. Anyway I was looking for this:

private (bool start, bool end) InInterval(int lower, int upper)
{
    return (5 < lower && lower < 10, 5 < upper && upper < 10);
}

private string Test()
{
	var response = InInterval(2, 6);
	if (!response.start && !response.end)
		return "The interval did not start nor end inside the target";
	else if (!response.start)
		return "The interval did not start inside the target";
	else if (!response.end)
		return "The interval did not end inside the target";
	else
		return "The interval is inside the target";
}

Another style to call this could be:

	var (start, end) = InInterval(2, 6);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfrenchieView Question on Stackoverflow
Solution 1 - C#abatishchevView Answer on Stackoverflow
Solution 2 - C#Not lovedView Answer on Stackoverflow
Solution 3 - C#Rosdi KasimView Answer on Stackoverflow
Solution 4 - C#Justin PihonyView Answer on Stackoverflow
Solution 5 - C#craigrs84View Answer on Stackoverflow
Solution 6 - C#SandeepView Answer on Stackoverflow
Solution 7 - C#IvoView Answer on Stackoverflow
Solution 8 - C#AlbertKView Answer on Stackoverflow
Solution 9 - C#Chuck NorrisView Answer on Stackoverflow
Solution 10 - C#BastardoView Answer on Stackoverflow
Solution 11 - C#Imran JalaliView Answer on Stackoverflow
Solution 12 - C#Mehmet YAŞARView Answer on Stackoverflow
Solution 13 - C#Daniel LidströmView Answer on Stackoverflow
Solution 14 - C#alhpeView Answer on Stackoverflow
Solution 15 - C#MaslowView Answer on Stackoverflow
Solution 16 - C#Damian VogelView Answer on Stackoverflow