views:

72

answers:

5

I have a generic interface:

public interface IUnauthorizedRequestRespondable<out T> where T:class 
{
    T GetResponseForUnauthorizedRequest();
}  

(I'm not sure why Resharper recommended T is "out", but that's not the question).
In my scenario, the object returned by GetResponseForUnauthorizedRequest is always of the type that implements the interface.

So all the interface's implementations look like:

public class SignInReturnedObject : IUnauthorizedRequestRespondable<SignInReturnedObject>  

(class name and the type in brackets are always the same).
Which seems a bit awkward - isn't there a neater way to tell the compiler that the interface's method returns the type it's a part of?

Thanks.

+3  A: 

As far as I know, there is no way to do that currently in C#.

A theoretical side-note: The feature that would allow you to do this is called self types but that's not available in C#. The idea of the feature is that you have a special type that refers to the actual type of this, so if you had a special type named self, you could probably write something like:

public interface IUnauthorizedRequestRespondable { 
    self GetResponseForUnauthorizedRequest(); 
}   

...and the actual type used in place of self when you have a class SignInReturnedObject implementing the interface would be SignInReturnedObject, but unfortunatelly, that's not
available in C# :-)

Tomas Petricek
A: 

Actually, that about sums it up. That is how the syntax works.

You can see it used in .NET itself with the IEquatable inteface--you are almost always comparing an object to itself, yet you always have to provide your own class name as a template parameter.

This is simply to provide flexibility such that you can compare to anything, not necessarily yourself.

Stargazer712
A: 

You can create a nongeneric version and just use that but I think it is more trouble than it is worth

public interface ICastUnauthorizedRequestRespondable : IUnauthorizedRequestRespondable<SignInReturnedObject>
{
}  
Scott Chamberlain
A: 

Since T can be any class (does not have to be the class you are implementing) you need to name your class.

public class SignInReturnedObject : IUnauthorizedRequestRespondable<ANYCLASS>
Numenor
+1  A: 

If the only way you want to use that template is in that manner, I would use:

public interface IUnauthorizedRequestRespondable<T> where T:IUnauthorizedRequestRespondable<T>
{
    T GetResponseForUnauthorizedRequest();
}

This has the advantage of guaranteeing it isn't used in any other way.

The class declaration won't change, but I don't see anything as awkward in this myself. Considering that you are defining a relationship between the class and itself, any more concise form might be inadvisable.

Jon Hanna