Anonymous types are class types that derive directly from object , and that cannot be cast to any type except object . The compiler provides a name for each anonymous type, although your application cannot access it.
Try this: Func<string> temp = () => {return "test";}; You can now execute the function thusly: string s = temp();
The compiler gives them a name although your application cannot access it. From the perspective of the common language runtime, an anonymous type is no different from any other reference type, except that it cannot be cast to any type except for object.
Definition. Anonymous type, as the name suggests is a type that doesn't have any name. Anonymous types are the new concept in C#3.0 that allow us to create new type without defining them. This is a way to define read only properties into a single object without having to define type explicitly.
I tend to go for this pattern:
public class DogWithBreed
{
public Dog Dog { get; set; }
public string BreedName { get; set; }
}
public IQueryable<DogWithBreed> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new DogWithBreed()
{
Dog = d,
BreedName = b.BreedName
};
return result;
}
It means you have an extra class, but it's quick and easy to code, easily extensible, reusable and type-safe.
You can return anonymous types, but it really isn't pretty.
In this case I think it would be far better to create the appropriate type. If it's only going to be used from within the type containing the method, make it a nested type.
Personally I'd like C# to get "named anonymous types" - i.e. the same behaviour as anonymous types, but with names and property declarations, but that's it.
EDIT: Others are suggesting returning dogs, and then accessing the breed name via a property path etc. That's a perfectly reasonable approach, but IME it leads to situations where you've done a query in a particular way because of the data you want to use - and that meta-information is lost when you just return IEnumerable<Dog>
- the query may be expecting you to use (say) Breed
rather than Owner
due to some load options etc, but if you forget that and start using other properties, your app may work but not as efficiently as you'd originally envisaged. Of course, I could be talking rubbish, or over-optimising, etc...
Just to add my two cents' worth :-) I recently learned a way of handling anonymous objects. It can only be used when targeting the .NET 4 framework and that only when adding a reference to System.Web.dll but then it's quite simple:
...
using System.Web.Routing;
...
class Program
{
static void Main(string[] args)
{
object anonymous = CallMethodThatReturnsObjectOfAnonymousType();
//WHAT DO I DO WITH THIS?
//I know! I'll use a RouteValueDictionary from System.Web.dll
RouteValueDictionary rvd = new RouteValueDictionary(anonymous);
Console.WriteLine("Hello, my name is {0} and I am a {1}", rvd["Name"], rvd["Occupation"]);
}
private static object CallMethodThatReturnsObjectOfAnonymousType()
{
return new { Id = 1, Name = "Peter Perhac", Occupation = "Software Developer" };
}
}
In order to be able to add a reference to System.Web.dll you'll have to follow rushonerok's advice : Make sure your [project's] target framework is ".NET Framework 4" not ".NET Framework 4 Client Profile".
In C# 7 you can now use tuples!... which eliminates the need to create a class just to return the result.
Here is a sample code:
public List<(string Name, string BreedName)> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
}.ToList();
return result.Select(r => (r.Name, r.BreedName)).ToList();
}
You might need to install System.ValueTuple nuget package though.
No you cannot return anonymous types without going through some trickery.
If you were not using C#, what you would be looking for (returning multiple data without a concrete type) is called a Tuple.
There are alot of C# tuple implementations, using the one shown here, your code would work like this.
public IEnumerable<Tuple<Dog,Breed>> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new Tuple<Dog,Breed>(d, b);
return result;
}
And on the calling site:
void main() {
IEnumerable<Tuple<Dog,Breed>> dogs = GetDogsWithBreedNames();
foreach(Tuple<Dog,Breed> tdog in dogs)
{
Console.WriteLine("Dog {0} {1}", tdog.param1.Name, tdog.param2.BreedName);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With