views:

458

answers:

4

After looking at how Go handles interfaces and liking it, I started thinking about how you could achieve similar duck-typing in C# like this:

var mallard = new Mallard(); // doesn't implement IDuck but has the right methods
IDuck duck = DuckTyper.Adapt<Mallard,IDuck>(mallard);

The DuckTyper.Adapt method would use System.Reflection.Emit to build an adapter on the fly. Maybe somebody has already written something like this. I guess it's not too different from what mocking frameworks already do.

However, this would throw exceptions at run-time if Mallard doesn't actually have the right IDuck methods. To get the error earlier at compile time, I'd have to write a MallardToDuckAdapter which is exactly what I'm trying to avoid.

Is there a better way?

edit: apparently the proper term for what I call "safe duck-typing" is structural typing.

+4  A: 

DuckTyping for C#

Reflection.Emit is used to emit IL that directly calls the original object

I don't think this library will give you compile time errors thought, I am not sure that would be entirely feasible. Use Unit Tests to help compensate for that.

Bob
Released under the Artistic License 2.0!
Martinho Fernandes
+1 I like the idea of using unit tests here. This way you trade the (potentially large) overhead of writing an adapter class for the small overhead of writing a single-line unit test.
Wim Coenen
+5  A: 

How can you know if a cow walks like a duck and quacks like a duck if you don't have a living, breathing cow in front of you?

Duck-typing is a concept used at run-time. A similar concept at compile-time is structural typing which is AFAIK not supported by the CLR. (The CLR is centred around nominative typing.)

[A structural type system] contrasts with nominative systems, where comparisons are based on explicit declarations or the names of the types, and duck typing, in which only the part of the structure accessed at runtime is checked for compatibility.

The usual way to ensure that duck-typing throws no exception at run-time are unit-tests.

dtb
In Go, duck-typing is something that is verified statically. The compiler looks at the Cow class and complains if it doesn't have the duck methods.
Wim Coenen
That's exactly the definition of structural inheritance :-)
dtb
In .NET, duck typing is used differently from the usual meaning of the term. Unfortunately, re-branding established technical terms has become something of a company hobby at Microsoft (or at least in the CLR department), which is extremely annoying.
Konrad Rudolph
Ah, I see what you mean now. It's called "structural typing", not "structural inheritance". http://en.wikipedia.org/wiki/Structural_typing
Wim Coenen
D'oh. You're right. I even have that book (*Types and programming languages*, recommended!!) on my shelf, although I haven't touched it in a while...
dtb
+1  A: 

I don't think there's another way in which you would get a compile time error.

However, this is something that Unit Testing is great for. You would write a unit test to verify that

DuckTyper.Adapt<Mallard, IDuck>(mallard);

successfully maps.

Joseph
+1  A: 

I know that implicit interfaces (which is what Go interfaces are) were planned for VB 10 (no idea about C#). Unfortunately, they were scrapped before release (I think they didn’t even make it into beta …). It would be nice to see whether they will make an appearance in a future version of .NET.

Of course, the new dynamic types can be used to achieve much the same but this is still not the same – implicit interfaces still allow strong typing, which I find important.

Konrad Rudolph
Could you provide links to support your claim concerning implicit interfaces in VB?
Dario