17

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.

Wim Coenen
  • 66,094
  • 13
  • 157
  • 251
  • I've wished for this before, adapting the System.xml.serialization system to work with the generic system.runtime.serialization formatters. – Joel Coehoorn Nov 13 '09 at 17:27
  • 1
    Also: does Go check this at compile-time, or just run-time? If the latter, they haven't provided any new solutions to the problem, just the extra Adapt code you already mentioned. – Joel Coehoorn Nov 13 '09 at 17:29
  • Yeah, writing the adapter would not qualify as duck typing, because it's regular C# typing... – R. Martinho Fernandes Nov 13 '09 at 17:29

4 Answers4

14

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
  • 213,145
  • 36
  • 401
  • 431
  • 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 Nov 13 '09 at 17:31
  • 3
    That's exactly the definition of structural inheritance :-) – dtb Nov 13 '09 at 17:32
  • 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 Nov 13 '09 at 17:36
  • 1
    Ah, I see what you mean now. It's called "structural typing", not "structural inheritance". http://en.wikipedia.org/wiki/Structural_typing – Wim Coenen Nov 13 '09 at 17:44
  • 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 Nov 13 '09 at 17:53
  • A note from the future (but it seems it was already a fact back in 2009): both [F#](http://codebetter.com/matthewpodwysocki/2009/06/11/f-duck-typing-and-structural-typing/) and [Scala](http://java.dzone.com/articles/duck-typing-scala-structural) have structural types, without any direct support from the VM. – rsenna Feb 27 '14 at 14:48
5

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
  • 97,670
  • 29
  • 122
  • 130
1

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
  • 25,330
  • 8
  • 76
  • 125
1

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
  • 530,221
  • 131
  • 937
  • 1,214