【问题标题】:How to declare generic event for generic delegate in c#如何在 C# 中为泛型委托声明泛型事件
【发布时间】:2018-09-22 00:30:21
【问题描述】:

我有一个处理文件上传的用户控件。我已经定义了一个委托如下

public delegate void FileUploadSuccess<T>(T value,FileUploadType F)

value 可以是字符串也可以是字节数组。 FileUploadType 是一个枚举,它告诉上传了哪种类型的文件。

现在我已经在用户控件中声明了一个事件来引发这个。

public event FileUploadSuccess<string> successString;   //In case I want a file name

public event FileUploadSuccess<Byte[]> successStringImage;  // In case I want a byte[] of uploaded image

我想要的是一个通用事件

public event FileUploadSuccess<T> successString. 

【问题讨论】:

    标签: c# .net


    【解决方案1】:

    除了作为泛型类型的一部分(即

    class Foo<T> { public event SomeEventType<T> SomeEventName; }
    

    ) 没有泛型属性、字段、事件、索引器或运算符(只有泛型类型和泛型方法)。这里的包含类型可以泛型吗?

    【讨论】:

      【解决方案2】:

      对于外界来说,一个事件在很多方面看起来就像是类的一个领域。正如您不能使用开放的泛型类型来声明字段一样,您也不能使用开放的泛型类型来声明事件。

      如果您可以让类型保持打开状态,那么编译器将不得不在事件处理程序中为您的泛型参数T 添加和删除每种可能类型的代码。封闭的泛型类型不能进行 JIT 编译,因为您的事件本身并不是一个类型,而是封闭类型的一部分。

      【讨论】:

        【解决方案3】:

        除非您在封闭类中定义类型参数,否则这是不可能的。例如:

        public delegate void FileUploadSuccess<T>(T value, FileUploadType F)
        
        public class FileUploader<T>
        {
            public event FileUploadSuccess<T> FileUploaded;
        }
        

        但这只会将您的问题转移到另一个位置,因为现在您必须声明 FileUploader 类的两个实例:

        FileUploader<string> stringUploader = new FileUploader<string>();
        FileUploader<byte[]> stringUploader = new FileUploader<byte[]>();
        

        这可能不是你想要的。

        【讨论】:

          【解决方案4】:

          为什么需要通用事件?你不能只使用一个正常的事件:

          public delegate void FileUploadSuccess(object value);
          

          然后

          public event FileUploadSuccess Success;
          

          在 Success 事件处理程序中,您将知道所传递对象的类型:

          public void SuccessHandler(object value)
          {
              // you know the type of the value being passed here
          }
          

          【讨论】:

          • 先生,我想让它类型安全,并考虑泛型是否可以提供帮助。
          【解决方案5】:

          我认为这是不可能的。

          事件就像一个委托的实例(粗略地说),一个实例是一个具体的实现(泛型或非泛型类)。

          为了更好地了解代表和事件,您可以参考this SO讨论。

          【讨论】:

            【解决方案6】:

            .Net 框架中有一个通用的 EventHandler 类就是为了这个目的:

            using System;
            
            namespace ConsoleApplication1
            {
                class Program
                {
                    static void Main(string[] args)
                    {
                        Counter c = new Counter(new Random().Next(10));
                        c.ThresholdReached += c_ThresholdReached;
            
                        Console.WriteLine("press 'a' key to increase total");
                        while (Console.ReadKey(true).KeyChar == 'a')
                        {
                            Console.WriteLine("adding one");
                            c.Add(1);
                        }
                    }
            
                    static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
                    {
                        Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold,  e.TimeReached);
                        Environment.Exit(0);
                    }
                }
            
                class Counter
                {
                    private int threshold;
                    private int total;
            
                    public Counter(int passedThreshold)
                    {
                        threshold = passedThreshold;
                    }
            
                    public void Add(int x)
                    {
                        total += x;
                        if (total >= threshold)
                        {
                            ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
                            args.Threshold = threshold;
                            args.TimeReached = DateTime.Now;
                            OnThresholdReached(args);
                        }
                    }
            
                    protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
                    {
                        EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
                        if (handler != null)
                        {
                            handler(this, e);
                        }
                    }
            
                    public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
                }
            
                public class ThresholdReachedEventArgs : EventArgs
                {
                    public int Threshold { get; set; }
                    public DateTime TimeReached { get; set; }
                }
            }
            

            来源:https://docs.microsoft.com/en-us/dotnet/api/system.eventhandler-1

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-01-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-12-07
              • 1970-01-01
              • 2022-01-16
              • 1970-01-01
              相关资源
              最近更新 更多