C # Generics lower bound "where MySubClass: T" (java "super")

I am wondering if C # has the equivalent of a common Java constraint <X super MySubClass>.

You can use to indicate an upper bound, class Foo<T> where T : MySuperClass { ... }but how can we determine the lower bound of a common parameter?


There are several ways to get similar results, but I have not yet found something perfect:

  • Use a second common parameter - but the caller can specify a subclass of the actual lower bound.

    public class Foo<T, TLowerBound>
        where TLowerBound : MySubClass
        where TLowerBound : T
    {
        ...
    }
    
  • It was once used in extension methods, so the extension method parameter is Ulimited to the superclass of the class parameter T.

    public static class Extensions {
        public static void Method<T, U>(this Foo<T> self, U someU) where T : U {
            self.ValueOfTypeT = someU;
        }
    }
    
  • Use dispersion on interfaces, but I'm not sure if this can be used to indicate the lower bound of a common parameter.

+4
1

. 2 ( ) , , ( ). , , 3 ( , ).

public class A<T> // an argument to the generic method
{
}

public class B<S>
{
    public virtual R Fun<T>(A<T> arg) where S : T // illegal in C#/CLR
    {
        ...
    }
}

public class C<S> : B<S>
{
    public override R Fun<T>(A<T> arg)
    {
    }
}

. -, ( , , , Fun ):

public interface IFun<in T>
{
    R Fun<S>(B<S> self) where S : T;
    R Fun<S>(C<S> self) where S : T;
}

, T , . , B C "" :

public class B<S>
{
    public virtual R Perform(IFun<S> fun)
    // contravariant, any IFun<T> with S : T will be accepted
    {
        return fun.Fun(this);
    }
}

public class C<S> : B<S>
{
    public override R Perform(IFun<S> fun)
    {
        return fun.Fun(this);
    }
}

A<T>, struct/class, :

public struct TheFun<T> : IFun<T>
{
    public A<T> arg;

    R IFun<T>.Fun<S>(B<S> self)
    {
        ... body of B<S>.Fun(A<T> arg) ...
    }

    R IFun<T>.Fun<S>(C<S> self)
    {
        ... body of C<S>.Fun(A<T> arg) ...
    }
}

, , , 2:

public static class Extensions
{
    public static R Fun<S,T>(this B<S> self, A<T> arg) where S : T
    {
        return self.Perform(new TheFun<T> { arg = arg });
    }
}

. . :

  • ( )
  • B C TheFun, B C
+2

Source: https://habr.com/ru/post/1527205/


All Articles