C# Interfaces: Is it possible to refer to the type that implements the interface within the interface itself?

*爱你&永不变心* 提交于 2021-02-07 03:30:38

问题


What I basically wish to do is design a generic interface that, when implemented, results in a class that can behave exactly like T, except that it has some additional functionality. Here is an example of what I'm talking about:

public interface ICoolInterface<T>
{
    T Value { get; set; }
    T DoSomethingCool();
}

public class CoolInt : ICoolInterface<int>
{
    private int _value;

    public CoolInt(int value)
    {
        _value = value;
    }

    public int Value
    {
        get { return _value; }
        set { _value = value; }
    }

    public int DoSomethingCool()
    {
        return _value * _value;
        // Ok, so that wasn't THAT cool
    }
}

And this is all well and good, but in order to use CoolInt, I need to do something like this:

CoolInt myCoolInt = new CoolInt(5);
int myInt = myCoolInt.Value;

I'd much rather, in terms of assignment at least, that CoolInt works just like int. In other words:

CoolInt myCoolInt = 5;
int myInt = myCoolInt;

To achieve this, I added these two conversion operators to my CoolInt class:

    public static implicit operator CoolInt(int val)
    {
        return new CoolInt(val);
    }

    public static implicit operator int(CoolInt obj)
    {
        return obj.Value;
    }

Works awesomely. Now, I would prefer it if I could add these two overloads to the interface, so that implementers of the interface are forced to implement these operators. The problem is, the prototypes of these operators refer directly to CoolInt.

C# has a lot of "placeholder" names for things that are implicitly defined or have yet to be defined. The T that is conventionally used in generic programming is one example. I suppose the value keyword, used in Properties, is another. The "this" reference could be considered another. I am hoping that there's another symbol I can use in my interface to denote "the type of the class that is implementing this interface", e.g. "implementer".

    public static implicit operator implementer(int val)
    {
        return new IntVal(val);
    }

    public static implicit operator int(implementer obj)
    {
        return obj.Value;
    }

Is this possible?


回答1:


Sadly no :(

C# doesn't do well when it comes to operator overloading (This is one example, another is generic constraints on certain operator types).




回答2:


Why don't you create an abstract class? This way you can build some "default" functionality into your class.




回答3:


Why not use extension methods instead? That lets you "add" methods to int without having to use a different type.




回答4:


This is probably the closest you can get using an abstract base type, but sadly even this has an issue with one of the implicit operators and you have to do:-

        CoolInt x = (CoolInt)5;
        int j = x;

Close enough?

    // Slightly sneaky, we pass both the wrapped class and the wrapping class as type parameters to the generic class
    // allowing it to create instances of either as necessary.

    public abstract class CoolClass<T, U>
        where U : CoolClass<T, U>, new()
    {
        public T Value { get; private set; }

        public abstract T DoSomethingCool();

        // Non-public constructor
        protected CoolClass()
        {
        }

        public CoolClass(T value)
        {
            Value = value;
        }

        public static implicit operator CoolClass<T, U>(T val)
        {
            return new U() { Value = val};
        }

        public static implicit operator T(CoolClass<T, U> obj)
        {
            return obj.Value;
        }

    }

    public class CoolInt : CoolClass<int, CoolInt>
    {
        public CoolInt()
        { 
        }

        public CoolInt(int val)
            : base(val)
        {
        }

        public override int DoSomethingCool()
        {
            return this.Value * this.Value; // Ok, so that wasn't THAT cool
        }
    }



回答5:


It would be helpful if, at least for interfaces, one could declare that a class implements an interface in terms of an object; this would be especially cool if there was an "interface" generic type constraint. Then one could, for example, do something like (VB syntax)

Class Foo(Of T as Interface)
  Implements T via Bar  ' Declares variable 'bar' of type T
  Sub DoSomething
    ' Does something
  End Sub
End Class

and then cast a Foo(of T) to a T and have it behave like a T. Maybe someone from MS can stumble on the idea and pass it on?

I should note, btw, a nice pattern similar to your ICoolInterface:

public interface ISelf<T>
{
    T Self { get;}
}
public interface IFoozle
{
  ... definitions for IFoozle
}
public interface IFoozle<T> : ISelf<T> , IFoozle;
{
  /* Empty except for above declarations */
}
... similarly define IWoozle and IWoozle<T&gt etc.

Then one can declare a field which can implement IWoozle and IFoozle, and inherits from BoozleBase (which implements neither), via:

  IWoozle<IFoozle<BoozleBase>> myField1;
or
  IFoozle<IWoozle<BoozleBase>> myField2;

Note that the above two types can be cast to each other, or to types which also contain other interfaces. If one only needs to pass a variable meeting multiple constraints to a method, one can obtain such a thing more easily by using a generic method. Unfortunately, there's no way to store an object of unknown type in a field in such a way that it can be passed to a generic function with multiple constraints.



来源:https://stackoverflow.com/questions/3330294/c-sharp-interfaces-is-it-possible-to-refer-to-the-type-that-implements-the-inte

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!