分配给Delegate的通用方法

时间:2013-12-08 03:43:58

标签: c# generics types interface delegates

我对代表和通用方法感到有些困惑。

是否可以将委托分配给具有泛型类型参数的方法?

即:

//This doesn't allow me to pass a generic parameter with the delegate.
public delegate void GenericDelegate<T>() 

someDelegate = GenericMethod;
public void GenericMethod<T>() where T : ISomeClass
{

}

我正在尝试将此委托传递给函数,该函数具有该方法所期望的接口的泛型类型,具有如下函数:

void CheckDelegate(GenericDelegate<ISomeClass> mechanism);

这样我可以像这样使用委托:

someDelegate<ImplementsSomeClass>();

4 个答案:

答案 0 :(得分:10)

您的问题毫无意义,因为您无法使用开放的泛型类型来声明存储位置(如本地变量或字段)。它必须始终关闭。

我知道您希望将GenericDelegate<T>传递给采用此类值作为参数的方法。但即使这样,委托类型也会以T作为泛型类型参数关闭。

在您编写的示例代码中

someDelegate = GenericMethod;

但是someDelegate应该有什么类型?它必须显然是关闭的(GenericDelegate<string>)或者用外部范围中的泛型类型参数关闭:

void SomeOuterMethod<T>() where T : ISomeClass {
    GenericDelegate<T> someDelegate = GenericMethod<T>;
}

我希望我理解你的问题。如果没有,请澄清。如果你详细说明你想要完成什么,我会尝试提出一个切实可行的解决方案。

其他语言(如Haskell)确实支持传递开放泛型类型的值(换句话说,您可以使用类型为IEnumerable<>的变量)。这是实现monad所必需的。 CLR没有该功能。


新想法:您可以使用可以覆盖的泛型方法创建非泛型基类型而不是委托:

interface CheckHandler {
 public void Check<T>(T someArg);
}

希望涵盖您的方案。你无法自由传递任何CheckHandler。然后可以使用任意类型参数调用其Check方法。

答案 1 :(得分:3)

可以使用单个“thing”来操作多个参数类型,但Delegate类不适用于此类。相反,您需要定义一个接口。举个简单的例子:

public interface IMunger<TConstraint>
{
    void Munge<T>(ref T it) where T : TConstraint;
}
public class Cloner : IMunger<ICloneable>
{
    public void Munge<T>(ref T it) where T : ICloneable
    {
        if (typeof(T).IsValueType) // See text
            return;
        it = (T)(it.Clone());
    }
}

即使系统具有带有by-ref参数的预定义委托类型(因此例如ActByRef<ICloneable>将具有签名void Invoke(ref ICloneable p1)),这样的委托仅用于精确类型的变量ICloneable。相比之下,非泛型类类型Cloner的单个对象能够提供适用于实现ICloneable的任何存储位置类型的方法。另请注意,如果将方法传递给ref到包含对盒装值类型实例的引用的变量,它将使用对实例副本的引用替换它,但如果传递了ref 1}}到一个值类型变量,它保持原样(除非值类型将其状态保存在一个可变类对象中,它持有一个引用 - 一个非常狡猾的模式 - 说StructType foo = (StructType)(bar.Clone());会等同于foo = bar;结构类型可能希望实现ICloneable,以便允许它参与深度克隆层次结构,但这并不意味着它需要Clone方法做任何事。

答案 2 :(得分:1)

更新了示例以支持方法作为参数,该示例仅演示了如何将泛型委托作为其他方法的参数进行调用。

class Program
{
    public delegate T Transformer<T>(T arg) where T : IComparable;

    public static void Transform<T>(T value, Transformer<T> method) where T: IComparable
    {
        Console.WriteLine(method(value));
    }

    static void Main(string[] args)
    {
        Transform(5, Square);
    }

    static int Square(int x)
    {
        return x * x;
    }
}

答案 3 :(得分:0)

我尝试了以下内容:

public class Test
{
    public interface ISomeClass { }

    public class ImplementsSomeClass : ISomeClass { }

    public delegate void GenericDelegate<T>() where T : ISomeClass;

    public void GenericMethod<T>() 
    {
        // EDIT: returns typeof(ImplementsSomeClass)
        var t = typeof(T); 
    }

    public void CheckDelegate(GenericDelegate<ISomeClass> mechanism)
    {
        // EDIT: call without generic argument since it is already determined 
        mechanism(); 
    }

    public void test()
    {
        GenericDelegate<ISomeClass> someDelegate = GenericMethod<ImplementsSomeClass>;
        CheckDelegate(someDelegate);
    }
}

我没有编译错误。这是运行时问题还是我误解了你的问题描述?