Enhanced C#
Language of your choice: library documentation

Documentation moved to ecsharp.net

GitHub doesn't support HTTP redirects, so you'll be redirected in 3 seconds.

 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Events Pages
Static Public Member Functions | List of all members
Loyc.Utilities.GoInterface< Interface > Class Template Reference

GoInterface<Interface> creates wrappers around objects of your choosing that implement the specified Interface, forwarding calls to methods in the wrapped object. It is inspired by the duck-typed interfaces in the Go programming language. More...


Source file:

Remarks

GoInterface<Interface> creates wrappers around objects of your choosing that implement the specified Interface, forwarding calls to methods in the wrapped object. It is inspired by the duck-typed interfaces in the Go programming language.

In the Go programming language, you do not say explicitly that your type implements a given interface. Instead, a type is convertable to any interface, just so long as it implements all the methods in the interface. This often reminds people of "duck typing" in dynamic languages such as Python or Ruby, but it is faster; in fact, Go interface calls are the same speed as virtual method calls in C++ and C#!

To put it in C# terms, if you have a class T...

public class T {
    public void Foo(int x);
}

...and an interface called "Interface"...

public interface Interface {
    void Foo(int x);
}

...then you can cast T to Interface even though T does not explicitly implement it.

Interface t = new T();

This cast can be implicit since the compiler can tell at compile time that T implements the Interface. However, you can cast any object to Interface and, at run-time, Go will determine whether it implements the Interface.

I asked how Go dispatch works on the "Go Nuts" google group and was pointed to two articles:

http://research.swtch.com/2009/12/go-data-structures-interfaces.html http://www.airs.com/blog/archives/281

To summarize those, the first time you convert a type "T" to an interface "Interface", a vtable (virtual function table) is generated just like the kind used for virtual calls in .NET and C++. However, instead of storing the vtable in the object itself like C++ and .NET do, Go stores the vtable pointer alongside the interface pointer (i.e. an interface pointer is really two pointers). This simple but unique design allows a single object to implement an unlimited number of interfaces with overall performance that is competitive with C# and Java.

Unfortunately, as far as I can tell, there is no way to efficiently implement this same technique in .NET without changing the CLR itself. A virtual method table is just a list of pointers to functions; importantly, function pointers in a virtual method table are not associated with a specific object, which makes them different from .NET delegates. By not associating the vtable with a specific object, it is possible to re-use the same vtable with any number of objects (as long as they are of the same class). However, .NET delegates are associated with specific objects, so we can't use them to form a reusable vtable.

Even if .NET allowed delegates that are not associated with a specific object, delegate invocation on .NET is slower than virtual method invocation; why this is so is not entirely clear to me, but part of the reason may be that Microsoft decided to make delegates reference types when they should have been a simpler 8-byte value type (just bundling a function pointer with a 'this' pointer).

However, just a few days ago I learned that Visual Basic 9 has a very similar feature to Go called "dynamic interfaces", which pretty much lets you do as described above (albeit only in Visual Basic). So far I've heard nothing about how VB's dynamic interfaces work, but I got to thinking: how hard would it be to bring go-style interfaces to all .NET languages, and would it be possible to get good performance?

The technique I chose doesn't have performance as good as you would get from Go, but in exchange for a small performance hit (which I believe to be unavoidable anyway), the GoInterface classes provide automatic interface adaptations that you can't get in Go itself. Specifically, my GoInterface classes can automatically do small type conversion tasks like enlarging "int" to "long", boxing value types, and allowing return type covariance (for instance, if the wrapped method returns a "string", the Interface can return an "object".) And since GoInterface returns heap objects that actually implement the interface you ask for (rather than, say, an 8-byte structure imitating the Go implementation), it's very easy to use.

The GoInterface classes use .NET Reflection.Emit to generate wrapper classes in a "dynamic assembly"–basically a DLL that exists only in memory. Each wrapper class implements a single interface of your choosing, and forwards calls on that interface to an object of your choosing.

Given the types from above...

public class T {
    public void Foo(int x);
}
public interface Interface {
    void Foo(int x);
}

...you can use GoInterface to cast T to Interface like this:

Interface t = GoInterface<Interface>.From(new T());

The first time you cast a T to Interface, GoInterface generates a wrapper class such as the following on-the-fly:

public class T_46F3E18_46102A0 : Interface
{
    T _obj;
    public T_46F3E18_46102A0(T obj) { _obj = obj; }
    void Foo(int x) { _obj.Foo(x); }
}

The hex numbers in the name of the type are simply handles to interface and type being wrapped, in order to guarantee no name collisions occur when you are wrapping a lot of different classes with GoInterface.

After the first cast, all future casts are fairly fast, especially if you call GoInterface<Interface,T>.From() instead of just GoInterface<Interface>.From(). That's because after GoInterface<Interface,T> is fully initialized, all its From() method does is invoke a delegate that contains the following code:

delegate(T obj) { return new T_46F3E18_46102A0(obj); }

You can create wrappers with either GoInterface<Interface> or GoInterface<Interface, T> (note the extra type argument "T").

If you're not sure which one to use, use GoInterface<Interface>. If you need to adapt a large number of objects to a single interface, you should use GoInterface<Interface, T> where possible, because it is slightly faster. GoInterface<Interface>, in contrast, has to examine each object it is given to find out its most derived type. However, this process is optimized so that an expensive analysis is only done once per derived type, after which only a hashtable lookup is required.

Compared to interfaces in the Go programming language, which have a 1-word overhead for every interface pointer (the vtable pointer, which is 4 bytes in 32-bit code), GoInterface wrappers normally have 3 words of overhead (2 words for the wrapper's object header and 1 word for a reference to the wrapped object). Also, GoInterface wrapper classes are no doubt much more costly to produce (since they involve run-time code generation), which will increase your program's startup time and have a fixed memory overhead that dwarfs Go's implementation. However, once you are up-and-running with GoInterface wrappers, their performance should be pretty good. TODO: benchmarks

Note: GoInterface can create wrappers for value types (structures), not just classes. Such wrappers have the same memory overhead as boxed structures, which is one word less than wrappers for reference types.

GoInterface wrappers automatically forward calls to object.ToString(), object.GetHashCode() and object.Equals(), even though these methods are not technically part of the interface being wrapped.

GoInterface cannot wrap explicit interface implementations in the target class. For instance, if the target class implements IEnumerable(of T), that interface has two versions of the GetEnumerator function that differ only by return type (one returns IEnumerator and the other returns IEnumerator(of T)), so one of them must be implemented "explicitly". GoInterface will typically only see the version that returns IEnumerator(of T), but this is not a problem since IEnumerator(of T) is implicitly convertable to IEnumerator, so GoInterface can use that one method to represent either of them. In Visual Basic there is a caveat, since an explicit interface implementation is allowed to be public. In that case, GoInterface will only see the method's public name (not the name used in the interface).

Type Constraints
Interface :class 

Static Public Member Functions

static Interface From< T > (T anything)
 
static Interface ForceFrom< T > (T anything)
 
static Interface From< T > (T anything, CastOptions options)