C#Generics不允许委托类型约束

Nic*_*uso 76 c# generics events delegates constraints

是否可以在C#中定义一个类

class GenericCollection<T> : SomeBaseCollection<T> where T : Delegate
Run Code Online (Sandbox Code Playgroud)

我无法为我的生活在.NET 3.5中完成这一切.我试过用

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

在我看来,这应该是允许的某种方式.我正在尝试实现自己的EventQueue.

我最终只是这样做[原始近似注意你].

internal delegate void DWork();

class EventQueue {
    private Queue<DWork> eventq;
}
Run Code Online (Sandbox Code Playgroud)

但是后来我失去了为不同类型的函数重用相同定义的能力.

思考?

Mar*_*ell 65

许多类不作为通用约束 - Enum是另一个.

对于委托,最接近的是":class",也许使用反射来检查(例如,在静态构造函数中)T 委托:

static GenericCollection()
{
    if (!typeof(T).IsSubclassOf(typeof(Delegate)))
    {
        throw new InvalidOperationException(typeof(T).Name + " is not a delegate type");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • +1表示:1)使用静态构造函数和2)包含详细消息,因为类型初始化周围有奇怪的调试条件. (8认同)
  • @MarcGravell:不在静态初始化程序中抛出异常违反了"CA1065:不要在意外位置引发异常"......我总是假设您应该使用自定义代码分析规则来查找类的无效用法在运行时通常不可用. (6认同)
  • 从C#7.3(2018年5月发布)开始,允许这样约束,`其中T:Delegate`,(有人在下面发布了一个新答案). (3认同)

Jor*_*ira 13

编辑:这些文章中提出了一些拟议的解决方法:

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

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


C#2.0规范我们可以阅读(20.7,约束):

类类型约束必须满足以下规则:

  • 类型必须是类类型.
  • 该类型不得密封.
  • 该类型不能是以下类型之一:System.Array,System.Delegate,System.Enum或System.ValueType.
  • 类型不能是对象.因为所有类型都是从对象派生的,所以如果允许这样的约束就没有效果.
  • 给定类型参数的最多一个约束可以是类类型.

确定VS2008吐出错误:

error CS0702: Constraint cannot be special class 'System.Delegate'
Run Code Online (Sandbox Code Playgroud)

有关此问题的信息和调查,请阅读此处.


Sim*_*mon 10

如果您愿意对IL Weaver采用编译时依赖性,则可以使用Fody执行此操作.

将此插件用于Fody https://github.com/Fody/ExtraConstraints

您的代码可能如下所示

public class Sample
{
    public void MethodWithDelegateConstraint<[DelegateConstraint] T> ()
    {        
    }
    public void MethodWithEnumConstraint<[EnumConstraint] T>()
    {
    }
} 
Run Code Online (Sandbox Code Playgroud)

并编译成这个

public class Sample
{
    public void MethodWithDelegateConstraint<T>() where T: Delegate
    {
    }

    public void MethodWithEnumConstraint<T>() where T: struct, Enum
    {
    }
}
Run Code Online (Sandbox Code Playgroud)


msh*_*hwf 10

是的,它是在C#7.3可能,限制家庭扩大至包括Enum,Delegateunmanaged类型.您可以毫无问题地编写此代码:

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

    }
Run Code Online (Sandbox Code Playgroud)

有用的链接:

C#的未来,来自Microsoft Build 2018

C#7.3有什么新东西?