399

Is it possible to have an anonymous type implement an interface. I've got a piece of code that I would like to work, but don't know how to do this.

I've had a couple of answers that either say no, or create a class that implements the interface construct new instances of that. This isn't really ideal, but I'm wondering if there is a mechanism to create a thin dynamic class on top of an interface which would make this simple.

public interface DummyInterface
{
    string A { get; }
    string B { get; }
}

public class DummySource
{
    public string A { get; set; }
    public string C { get; set; }
    public string D { get; set; }
}

public class Test
{
    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new
                     {
                         A = value.A,
                         B = value.C + "_" + value.D
                     };

        DoSomethingWithDummyInterface(values);

    }

    public void DoSomethingWithDummyInterface(IEnumerable<DummyInterface> values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

I've found an article Dynamic interface wrapping that describes one approach. Is this the best way of doing this?


7 답변


313

No, anonymous types cannot implement an interface. From the C# programming guide:

Anonymous types are class types that consist of one or more public read-only properties. No other kinds of class members such as methods or events are allowed. An anonymous type cannot be cast to any interface or type except for object.


  • +1 - Use of anonymous types should typically be limited to lambda and LINQ expressions... as soon as the data is being exposed to callers that need to "do something" with the object, its a very good idea to implement a concrete class. - Mark
  • @Mark: I like using anonymous types as DTOs too. With auto mapping working pretty well in some scenarios. - boj
  • would be nice to have this stuff anyway. If you're talking code readability, lambda expressions are usually not the way to go. If we're talking RAD, I'm all into java-like anonymous interface implementation. By the way, in some cases that feature is more powerful than delegates - Arsen Zahray
  • @ArsenZahray: lambda expressions, when used well, actually increase code readability. They're particularly powerful when used in functional chains, which can reduce or eliminate the need for local variables. - Roy Tinker
  • @DmitryPavlov, that was surprisingly valuable. Passersby: here is the condensed version. - kdbanman

82

While this might be a two year old question, and while the answers in the thread are all true enough, I cannot resist the urge to tell you that it in fact is possible to have an anonymous class implement an interface, even though it takes a bit of creative cheating to get there.

Back in 2008 I was writing a custom LINQ provider for my then employer, and at one point I needed to be able to tell "my" anonymous classes from other anonymous ones, which meant having them implement an interface that I could use to type check them. The way we solved it was by using aspects (we used PostSharp), to add the interface implementation directly in the IL. So, in fact, letting anonymous classes implement interfaces is doable, you just need to bend the rules slightly to get there.


  • This is exactly the sort of behaviour I actively avoid. Compile on another machine and the whole thing goes pop. - Gusdor
  • I like the bending the rules part ;) - Beatles1692
  • @Gusdor, in this case, we had complete control over the build, and it was always run on a dedicated machine. Also, since we were using PostSharp, and what we were doing is fully legal within that framework, nothing could really go pop as long as we made sure PostSharp was installed on the build server we were using. - Mia Clarke
  • @Gusdor I agree it should be easy for other programmers to get the project and compile without great amount of difficulty, but that is a different issue addressable separately, without completely avoiding tooling or frameworks like postsharp. The same argument you make could be made against VS itself or any other non-standard MS framework that aren't part of the C# spec. You need those things or else it "goes pop". That's not a problem IMO. The problem is when the build becomes so complicated that it's difficult to get those things all working together right. - AaronLS
  • @ZainRizvi No, it didn't. As far as I know, it's still in production. The concern raised seemed strange to me then, and arbitrary at best to me now. It was basically saying "Don't use a framework, things will break!". They didn't, nothing went pop, and I'm not surprised. - Mia Clarke

41

Casting anonymous types to interfaces has been something I've wanted for a while but unfortunately the current implementation forces you to have an implementation of that interface.

The best solution around it is having some type of dynamic proxy that creates the implementation for you. Using the excellent LinFu project you can replace

select new
{
  A = value.A,
  B = value.C + "_" + value.D
};

with

 select new DynamicObject(new
 {
   A = value.A,
   B = value.C + "_" + value.D
 }).CreateDuck<DummyInterface>();


  • Impromptu-Interface Project will do this in .NET 4.0 using the DLR and is lighter weight then Linfu. - jbtule
  • Is DynamicObject a LinFu type? System.Dynamic.DynamicObject only has a protected constructor (at least in .NET 4.5). - jdmcnair
  • Yes. I was referring to the LinFu implementation of DynamicObject which predates the DLR version - Arne Claassen

12

No; an anonymous type can't be made to do anything except have a few properties. You will need to create your own type. I didn't read the linked article in depth, but it looks like it uses Reflection.Emit to create new types on the fly; but if you limit discussion to things within C# itself you can't do what you want.


  • And important to note: properties may include functions or voids (Action) as well: select new { ... MyFunction = new Func<string,bool>(s => value.A == s) } works though you cannot refer to new properties in your functions (we can't use "A" in lieu of "value.A"). - cfeduke
  • Well, isn't that just a property that happens to be a delegate? It isn't actually a method. - Marc Gravell
  • I've used Reflection.Emit to create types at runtime but believe now I would prefer an AOP solution to avoid the runtime costs. - Norman H

12

Anonymous types can implement interfaces via a dynamic proxy.

I wrote an extension method on GitHub and a blog post http://wblo.gs/feE to support this scenario.

The method can be used like this:

class Program
{
    static void Main(string[] args)
    {
        var developer = new { Name = "Jason Bowers" };

        PrintDeveloperName(developer.DuckCast<IDeveloper>());

        Console.ReadKey();
    }

    private static void PrintDeveloperName(IDeveloper developer)
    {
        Console.WriteLine(developer.Name);
    }
}

public interface IDeveloper
{
    string Name { get; }
}


11

The best solution is just not to use anonymous classes.

public class Test
{
    class DummyInterfaceImplementor : IDummyInterface
    {
        public string A { get; set; }
        public string B { get; set; }
    }

    public void WillThisWork()
    {
        var source = new DummySource[0];
        var values = from value in source
                     select new DummyInterfaceImplementor()
                     {
                         A = value.A,
                         B = value.C + "_" + value.D
                     };

        DoSomethingWithDummyInterface(values.Cast<IDummyInterface>());

    }

    public void DoSomethingWithDummyInterface(IEnumerable<IDummyInterface> values)
    {
        foreach (var value in values)
        {
            Console.WriteLine("A = '{0}', B = '{1}'", value.A, value.B);
        }
    }
}

Note that you need to cast the result of the query to the type of the interface. There might be a better way to do it, but I couldn't find it.


  • You could use values.OfType<IDummyInterface>() instead of cast. It only returns the objects in your collection that actually can be cast to that type. It all depends on what you want. - Kristoffer L

7

The answer to the question specifically asked is no. But have you been looking at mocking frameworks? I use MOQ but there's millions of them out there and they allow you to implement/stub (partially or fully) interfaces in-line. Eg.

public void ThisWillWork()
{
    var source = new DummySource[0];
    var mock = new Mock<DummyInterface>();

    mock.SetupProperty(m => m.A, source.Select(s => s.A));
    mock.SetupProperty(m => m.B, source.Select(s => s.C + "_" + s.D));

    DoSomethingWithDummyInterface(mock.Object);
}

Linked


Latest