分配给委托的通用方法
Posted
技术标签:
【中文标题】分配给委托的通用方法【英文标题】:Generic Method assigned to Delegate 【发布时间】:2013-12-25 07:46:07 【问题描述】:我对委托和通用方法有点困惑。
是否可以将委托分配给具有泛型类型参数的方法?
IE:
//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>();
【问题讨论】:
someDelegate
看起来像什么? (你得到了什么错误?)
公共委托 void GenericDelegate您的问题毫无意义,因为您永远不能使用开放的泛型类型来声明存储位置(如局部变量或字段)。它必须始终关闭。
我了解您希望将 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
方法。
【讨论】:
我正在尝试修改对象的状态。类型 T 将指定对象需要转换到的状态。 很好地解释了为什么不能将代理称为someDelegate<ClassThatImplementsSomeClass>();
。我完全同意。
所以这是不可能的,因为当我将它作为 可能有一个“事物”可以对多种参数类型进行操作,但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
传递给一个值类型变量,它保持原样(除非值类型将其状态保存在一个可变类对象中,它持有一个引用 - 一个非常狡猾的模式 - 说StructType foo = (StructType)(bar.Clone());
将等同于@987654331 @; 结构类型可能想要实现ICloneable
以便允许它参与深度克隆层次结构,但这并不意味着它的Clone
方法需要做任何事情。
【讨论】:
【参考方案3】:更新示例以支持方法作为参数,这只是说明如何将泛型委托作为其他方法的参数调用。
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;
【讨论】:
【参考方案4】:我尝试了以下方法:
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);
而且我没有编译错误。是运行时问题还是我误解了您的问题描述?
【讨论】:
我想用泛型参数调用委托。 someDelegatesomeDelegate = GenericMethod<ImplementsSomeClass>;
之后你不能用不同的参数调用它。有关更多信息,请参阅 usr 的答案。以上是关于分配给委托的通用方法的主要内容,如果未能解决你的问题,请参考以下文章