Search code examples
c#linqprojection

C# Linq Projecting Anonymous type onto an interface


Is it possible to project using a Select onto a anonymous type?

Here is some example code

public interface ITest
{
    string A{get;}
    int B{get;}
}

string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IQueryable<ITest> query =
    from     n in names.AsQueryable()
    select   new {A = n.ToUpper(), B = 2012};

The above code causes a

Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Linq.IQueryable'

Note: I can make the above code work if I were to define a class Test that implements ITest and then project into that class using:

select   new Test {A = n.ToUpper(), B = 2012};

Why? I am trying to see if I can only define the interface and not have to define the concrete implementation of the object and have Linq create me the object.


Solution

  • Yes, you can select into an anonymous type, but you can't both select into an anonymous type and then use those objects as if they implemented an interface. The reason is that the anonymous type doesn't implement the interface even though they have the same properties, in both type and name. There isn't a way to define that an anonymous type implements an interface. If you want to use objects via their interface implementations, you have to select into a concrete type that implements that interface.

    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. From the perspective of the common language runtime, an anonymous type is no different from any other reference type.

    Ref: http://msdn.microsoft.com/en-us/library/bb397696.aspx

    I can certainly sympathize with your intent here. It would be nice if the compiler could intuit that the type meets the interface definition when the type is anonymous, but that's really only applicable when the interface consists strictly of read-only properties. The minute your interface defines properties with setters or methods, it's not possible for an anonymous type to implement it. On the other hand, if you're using the anonymous type as it's intended -- as a short-term temporary type for a particular use -- you can simply reference it's properties and you don't need the interface at all.

     var query = from     n in names.AsQueryable()
                 select   new {A = n.ToUpper(), B = 2012};
     foreach (var item in query)
     {
          Console.WriteLine( item.A );
     }