[C#] C # Generics no permitirá restricciones de tipo de delegado


Answers

Editar: Algunas propuestas de solución alternativa se proponen en estos artículos:

http://jacobcarpenters.blogspot.com/2006/06/c-30-and-delegate-conversion.html

http://jacobcarpenters.blogspot.com/2006_11_01_archive.html

De la especificación C # 2.0 podemos leer (20.7, Restricciones):

Una restricción de tipo de clase debe cumplir las siguientes reglas:

  • El tipo debe ser un tipo de clase.
  • El tipo no debe ser sellado.
  • El tipo no debe ser uno de los siguientes tipos: System.Array, System.Delegate, System.Enum o System.ValueType .
  • El tipo no debe ser objeto. Como todos los tipos se derivan del objeto, tal restricción no tendría ningún efecto si estuviera permitida.
  • Como máximo, una restricción para un parámetro de tipo determinado puede ser un tipo de clase.

Y, por supuesto, VS2008 escupe un error:

error CS0702: Constraint cannot be special class 'System.Delegate'

Para información e investigación sobre este tema lea here .

Question

¿Es posible definir una clase en C # tal que

class GenericCollection<T> : SomeBaseCollection<T> where T : Delegate

No podría, por mi vida, lograr esto anoche en .NET 3.5. Intenté usar

delegate, Delegate, Action<T> and Func<T, T>

Me parece que esto debería ser permitido de alguna manera. Estoy tratando de implementar mi propio EventQueue.

Terminé haciendo esto [aproximación primitiva te importa].

internal delegate void DWork();

class EventQueue {
    private Queue<DWork> eventq;
}

Pero luego pierdo la capacidad de reutilizar la misma definición para diferentes tipos de funciones.

¿Pensamientos?




Sí, es posible en C # 7.3, la familia de restricciones aumenta para incluir Enum , Delegate y tipos unmanaged . Puedes escribir este código sin ningún problema:

void M<D, E, T>(D d, E e, T* t) where D : Delegate where E : Enum where T : unmanaged
    {

    }

Enlaces útiles:

El futuro de C # , de Microsoft Build 2018

¿Qué hay de nuevo en C # 7.3?




Delegate ya admite el encadenamiento. ¿Esto no satisface tus necesidades?

public class EventQueueTests
{
    public void Test1()
    {
        Action myAction = () => Console.WriteLine("foo");
        myAction += () => Console.WriteLine("bar");

        myAction();
        //foo
        //bar
    }

    public void Test2()
    {
        Action<int> myAction = x => Console.WriteLine("foo {0}", x);
        myAction += x => Console.WriteLine("bar {0}", x);
        myAction(3);
        //foo 3
        //bar 3
    }

    public void Test3()
    {
        Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; };
        myFunc += x => { Console.WriteLine("bar {0}", x); return x + 1; };
        int y = myFunc(3);
        Console.WriteLine(y);

        //foo 3
        //bar 3
        //4
    }

    public void Test4()
    {
        Func<int, int> myFunc = x => { Console.WriteLine("foo {0}", x); return x + 2; };
        Func<int, int> myNextFunc = x => { x = myFunc(x);  Console.WriteLine("bar {0}", x); return x + 1; };
        int y = myNextFunc(3);
        Console.WriteLine(y);

        //foo 3
        //bar 5
        //6
    }

}



Como se mencionó anteriormente, no puede tener Delegados y Enum como una restricción genérica. System.Object y System.ValueType tampoco se pueden usar como una restricción genérica.

La solución puede ser si construyes una llamada apropiada en ti IL. Funcionará bien.

Este es un buen ejemplo de Jon Skeet.

http://code.google.com/p/unconstrained-melody/

He tomado mis referencias del libro de Jon Skeet C # en la edición del Depto. 3.




Links