我对代表和通用方法感到有些困惑。
是否可以将委托分配给具有泛型类型参数的方法?
即:
//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>();
答案 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);
}
}
我没有编译错误。这是运行时问题还是我误解了你的问题描述?