Lucas Meijer

Game Development Consultancy

19 Jan, 2009

interface implementing more specific returntype

It’s no secret I really like C#. Not all is happily ever after though:

public interface ICanDoSomething
{
    IAnimal FindAnimal();
}
 
public class Dog : IAnimal
{
}
 
public class DoSomething : ICanDoSometing
{
   Dog FindAnimal() //I want this to work!
   {
      return new Dog();
   }
}

Why does the FindAnimal method with the Dog returntype not satisfy the interface requirement of having a FindAnimal method that returns an IAnimal? Dog implements IAnimal. So people who
use DoSomething as an ICanDoSomething will get a IAnimal, but if you happen to know that the implementation of your ICanDoSomething is a DoSomething, then you get back a more specific type, that you can call dog-only methods on.

The same would go for allowing less specific method arguments. If the interface defines SomeMethod(Dog d), but I want my implementation to implement SomeMethod(IAnimal a), I should be allowed to do that.

Very annoying. Like always, I’m sure there actually is a good reason for this somewhere, but that doesn’t make it less annoying :) . Maybe this will get addressed with the whole Contravariance/invariance stuff in c#4. I can’t wait.

Anybody got an elegant workaround for this in the meantime?

Tags:

7 Responses to "interface implementing more specific returntype"

1 | Benoit FOULETIER

January 20th, 2009 at 10:26 am

Avatar

“if you happen to know that the implementation of your ICanDoSomething is a DoSomething”… in this case, as you say a) you’d have to know so b) you’d have to cast to DoSomething anyway, so it doesn’t seem that much worse to have to know that FindAnimal returns a dog, and cast to Dog too.
Although I’m with you, the issue shouldn’t be there to start with, I don’t see why the compiler can’t figure it out… maybe report this so they fix it in 4.0? And by 2012 we should have it in Mono, then Unity ;) !

What bugs me way more about interfaces is that you can’t declare fields, only properties… which makes UT’s very bad design choice of basing its editor on public fields all the more painful. The whole .NET forms framework, and VS’s grid editor (and BTW, Blade3D, the XNA equivalent of Unity), are based on properties, which are much more flexible and powerful for about a billion reasons. Once again with UT, simplicity wins over flexibility… and eventually comes back to bite you in the ass.

2 | lucas

January 20th, 2009 at 12:23 pm

Avatar

I don’t see your argument: “you have to cast it anyway”. I could very well have a method

void SomeMethod(DoSomething s)
{
Dog d = s.FindAnimal();
}

Right now I have to do a clunky workaround of:

public class DoSomething : ICanDoSomething
{
Dog FindAnimal_ItReallyIsADog()
{
return FindAnimal() as Dog;
}
}

I like the fact that an interface cannot specify public fields.
Fields belong to the implementation. Just use properties.
And yeah, Unity’s .NET API might not be used as an example in Framework Design Guidelines (http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756), it is quite easy to make a wrapper for the parts of the api you’d like to implement a specific interface. I’d love to see an example where this actually poses a problem.

3 | Benoit FOULETIER

January 21st, 2009 at 10:02 am

Avatar

Well… casting is clunky, I’m not denying that ;) !
What I meant is if your starting point is an ICanDoSomething, you ca have to check that it’s a DoSomething, cast it, then call FindAnimal and cast it as Dog… so you can make both casts in the same call. But you’re right which groups the ugliness.

4 | Benoit FOULETIER

January 21st, 2009 at 10:06 am

Avatar

Well… casting is clunky, I’m not denying that ;) !
What I meant is if your starting point is an ICanDoSomething, you call FindAnimal. Now you need to check if it’s actually a DoSomething anyway, so you can cast to Dog at that point. But you’re right, if you had isolated the fact that it was a DoSomething prior to that, then casting again is overkill.

5 | Benoit FOULETIER

January 21st, 2009 at 10:13 am

Avatar

“Fields belong to the implementation.”
Can’t agree more, the problem is that Unity uses fields for component setup, where it should be using properties (this way we could be notified when values change, etc etc, but I don’t need to preach the converted do I? ;) ).
As for an example, maybe I’d just like to have say an ILabel interface, so that I know that this component has a label field (which should be a property to start with)…

(The first post above got sent by mistake while I was typing, can you delete it?)

6 | Rodrigo

March 30th, 2009 at 3:54 pm

Avatar

I can’t think of a good reason why we can’t cast the way you want. But I got to this page looking for a way to do exactly what you want. And then a solution came to my mind “Generics” (and after lots of Google time) I got the perfect solution. Here it is what I found if you are still looking for a way to do that:

public interface IAnimal {}

public interface ICanDoSomething where T : IAnimal
{
T FindAnimal();
}

public class Dog : IAnimal {}

public class DoSomething : ICanDoSomething
{
public Dog FindAnimal()
{
return new Dog();
}
}

Nice isn’t it? But all the credit should go to these pages:
http://www.informit.com/articles/article.aspx?p=605369&seqNum=4
http://msdn.microsoft.com/en-us/library/132×8zxh.aspx

7 | Rodrigo

March 30th, 2009 at 3:59 pm

Avatar

Oops.. that got messed up after submit. Here it is again:

public interface IAnimal {}

public interface ICanDoSomething<T> where T : IAnimal
{
T FindAnimal();
}

public class Dog : IAnimal {}

public class DoSomething : ICanDoSomething<Dog>
{
public Dog FindAnimal()
{
return new Dog();
}
}

Comment Form

Game Development Consultancy

Hi. I'm Lucas Meijer. consultant on game development projects I work at Unity. You're looking at my portfolio website.

Please look around, and take a look at my work, my thoughts or more general information about myself.


If you have any questions regarding consulting, licensing of games, or anything else, feel free to email me at lucas@lucasmeijer.com

Contact Info

Lucas Meijer
lucas@lucasmeijer.com
lucasmeijer on twitter
ljmeijer on skype