.NET and duck-typing, part 1
Tags: net, ducktyping, csharp
Published: 2019-10-25 12:48:42

---
title: .NET and duck-typing, part 1
published: true
description: Duck-Typing: what is it, and how is it relevant to .NET?
tags: C#,.net,duck-typing
cover_image: https://thepracticaldev.s3.amazonaws.com/i/akueganqap85jfni3sz0.jpg
series: duck-typing
---

_"If it walks like a duck and it quacks like a duck, then it must be a duck"_

Well, close enough.

Duck-Typing is a phenomenon where you can treat an object as if it is of the type you want if it exhibits the properties that you require.

In some languages, like JavaScript, this is just "the way it's done". Whilst under-the-hood, the JavaScript engine will make clearly-defined types for objects you're wishing to represent, you can just go ahead and do:

```javascript
var animal = {
  walks: "like-a-duck",
  quacks: "like-a-duck",
  doStuff: function() {
    console.log("does stuff like a duck does");
  }
};

function doStuffIfDuck(animal) {
  // if the incoming animal is a good-enough
  // duck-like thing, then we can treat it like
  // a duck!
  if (animal.walks === "like-a-duck" &&
      animal.quacks === "like-a-duck" &&
      typeof(animal.doStuff) === "function") {
    animal.doStuff();
  }
}
```

All good and well, but JavaScript is not (technically) a strongly-typed language -- although variables do have type, it's quite valid to do:
```javascript
var foo = 1;
console.log(typeof foo); // logs "number"
foo = "a";
console.log(typeof foo); // logs "string"
```
where, in a more strongly-typed language like C#, this would just lead to compile errors, mostly because `var` is just compiler syntax-sugar which says "work out what type this variable would be, and that's the type it is".

But did you know that the C# compiler has been doing duck-typing since, well, forever?

## A Tale of Collections

I'm sure everyone has seen code like this in C# before:
```csharp
// before LINQ, there was a lot more of this, but it
//  still serves as an example:

var total = 0;
foreach (var item in collectionOfNumbers)
{
  total += item;
}
```

How does this work? You might be tempted to say that, well, the type of `collectionOfNumbers` implements `IEnumerable<int>` (ie `collectionOfNumbers` might be of type `int[]` or `List<int>`). But it's also quite possible that `collection` _doesn't implement any interface at all_.

Yeah, stop and think about that for a while.

Now have a look at this:

```csharp
using NUnit.Framework;
using static NExpect.Expectations;
using NExpect;

[TestFixture]
public class EnumerationIsDoneByDuckTyping
{
    [Test]
    public void ShouldBeAbleToEnumerate()
    {
        // Arrange
        var data = new[] { 1, 2, 3 };
        var enumerable = new MyEnumerable<int>(data);
        var collector = new List<int>();
        // Act
        foreach (var item in enumerable)
        {
            collector.Add((int) item);
        }

        // Assert
        Expect(collector).To.Equal(data);
    }

    // technically, does not neet to be generic: this
    // could just deal with objects, but I like a good
    // generic :D
    public class MyEnumerable<T>
    {
        private readonly T[] _data;

        public MyEnumerable(T[] data)
        {
            _data = data;
        }

        public MyEnumerator<T> GetEnumerator()
        {
            return new MyEnumerator<T>(_data);
        }
    }

    public class MyEnumerator<T>
    {
        public T Current => _data[_index];

        private readonly T[] _data;
        private int _index;

        public MyEnumerator(T[] data)
        {
            _data = data;
            Reset();
        }

        public bool MoveNext()
        {
            _index++;
            return (_index < _data.Length);
        }

        public void Reset()
        {
            _index = -1;
        }
    }
}
```

Not only does this compile, it runs, and the test passes. You're welcome to verify on your own machine (you'll need to install packages `NUnit` and `NExpect`). Yes, I know it's a little contrived. Imagine that this was wrapped around sequential HTTP calls, for instance. Or perhaps it wraps around something taking user input on the console, where an empty input signals the end of the collection. You can see an example of this on [GitHub](https://github.com/fluffynuts/duck-typed-foreach-in-csharp/blob/master/Colors/Program.cs)

Of course, you could just implement `IEnumerable`, but there was a bit of a chicken-and-egg situation there In The Beginning, and, at the end of the day, you simply need to satisfy the requirements of the compiler to be able to emit code to enumerate over your collection.

But how does this work?

## What is this dark magick?

When the C# compiler observes a `foreach` loop, it just looks to validate a few small criteria. In essence, there are two duck-typed requirements:

1. The item being looped over must implement a method called `GetEnumerator()`
2. The result of `GetEnumerator()` must conform to the expected shape for an enumerator:
   1. Implements a `Current` property which returns an object
   2. Implements a `MoveNext` method which moves the focus of the `Current` property forward and returns true if the collection is not yet exhausted (otherwise false)
   3. Implements a `Reset()` method with no return (`void`) which can start the enumeration again.

The C# compiler is performing this two-tier duck-typing test for you and emitting IL which does:
1. Fetch the enumerator
2. Call `MoveNext()` -- if the result is false, break out
3. Feed the value of `Current` into your loop
4. Lather, Rinse, Repeat.

This is interesting because it may not be what you expected from a strongly-typed language. It's also interesting because a similar approach was taken when implementing `async/await`, so it's not just some older design decision: this is a valid way to implement features!

In a later post, I'd like to demonstrate how we could duck-type any valid object onto our own interface, using a library I wrote called [PeanutButter.DuckTyping](https://nuget.org/packages/PeanutButter.DuckTyping). This library has saved me a lot of time when I want to have a well-defined interface for things like:
- ConnectionStrings from app.config
- AppSettings from app.config
- Arbitrary dictionaries and JSON objects
- Concrete types coming from other assemblies, where I'd like to be able to fake them out for testing (ie, the case when you say "I _wish_ this had an interface!")