简体   繁体   中英

Implementing a generic interface

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.

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# :-)

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.

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.

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>
{
}  

由于T可以是任何类(不必是您正在实现的类),因此您需要为您的类命名。

public class SignInReturnedObject : IUnauthorizedRequestRespondable<ANYCLASS>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM