【问题标题】:C#: public Delegates: Invoke from different classesC#:public Delegates:从不同的类调用
【发布时间】:2020-04-11 05:54:42
【问题描述】:

我在一个单独的类中定义了一个公共委托及其静态成员(返回对象类型),并试图从不同的 winform 调用它。然后,这些 winform 将检查委托成员返回的类型,然后适当地进行转换。到目前为止,一切都很好。但是,Visual Studio 抱怨我在每个 winform 中声明的委托类型从未分配给它,它的值将始终为空。

警告是:

警告 CS0649 字段“AccountReplenish.transferDelegate”从未分配给 AccountReplenish.cs 中的 ETTA,其默认值始终为 null

另外,在 AccountReplenish 中,如何调用委托类的 GetData()? 这是我的代码:

namespace ETTA.Classes
{
    public class DelegateClass
    {

        public delegate void TransferDelegate(object data);
        public TransferDelegate transferDelegate;
        private static object _receivedOutput = new object();
        public DelegateClass()
        {
            this.transferDelegate += new ETTA.Classes.DelegateClass.TransferDelegate(ReceiveOutput);
        }
        public static void ReceiveOutput(object data)
        {
            _receivedOutput = data;
        }
        public static object GetData()
        {
            return _receivedOutput;
        }
}

我的每个 winform 都会如下调用它:

public partial class AccoutnReplenish : Form
{
    private ETTA.Classes.DelegateClass.TransferDelegate transferObject;
    private object _receivedOutput = new object();

    public AccoutnReplenish()
    {
        this.transferObject= new Classes.DelegateClass.TransferDelegate (ETTA.Classes.DelegateClass.ReceiveOutput);
    }

    private void button_click(object sender, EventArgs e)
    {
      AutoReplenishWindow _progressWindow = new AutoReplenishWindow(transferObject);

      DialogResult dr = _progressWindow.ShowDialog(this);

      if (dr == System.Windows.Forms.DialogResult.OK )
         this._receivedOutput = ETTA.Classes.DelegateClass.GetData();
         if (this._receivedOutput != null && (this._receivedOutput.GetType() == typeof(string)))
             {
                string _s = (string)this._receivedOutput;
                MessageBox.Show("Result: " + _s);
             }
    }
}

public partial class AutoReplenishWindow : Form
    {
        private ETTA.Classes.DelegateClass.TransferDelegate transferObject;

        public AutoReplenishWindow()
        {
            InitializeComponent();
        }
        public AutoReplenishWindow(ETTA.Classes.DelegateClass.TransferDelegate del)
        {
            InitializeComponent();
            transferObject = del;
        }


        private async void AutoReplenishWindow_Shown(object sender, EventArgs e)
        {
            int arg1 = 12;
            string _result = await dbUtils.CallFunction(arg1);

            if (_result  != null && transferObject!= null)
            {                
                transferObject.Invoke(_result );                    
                this.Close();
            }
        }
    }

感谢任何帮助。 NH

编辑:我对上面的代码进行了一些编辑(见上文),它似乎工作正常。

【问题讨论】:

  • 您能否准确说明警告出现的位置?您在两个不同的类中有 TransferObject 字段,因此很难判断是哪个导致了问题。如果您可以将代码简化为正好重现问题所需的代码,然后将其格式化为更具可读性,这也会有所帮助。
  • AutoReplenishWindow 中的默认构造函数没有初始化transferDelegate。您可以通过类型名称DelegateClass.GetData() 访问静态成员。您可能更应该使用事件。请参阅:What are the differences between delegates and events?

标签: c# delegates public


【解决方案1】:

你应该做不同的事情。让我们举个例子。我将您的DelegateClass 更改为静态Transmitter 类,因为这就是它将数据从发送者传输到接收者的作用。它有一个任何接收者都可以订阅的公共事件。

public delegate void DataReceivedEventHandler(object data);

public static class Transmitter
{
    public static event DataReceivedEventHandler DataReceived;

    public static void TransmitData(object data)
    {
        DataReceived?.Invoke(data); // Raise the event.
    }
}

现在,让我们创建一个接收器表单,它可以显示它接收到的数据:

public partial class ReceiveDataForm : Form
{
    public ReceiveDataForm()
    {
        InitializeComponent();

        // Subscribe the event
        Transmitter.DataReceived += Transmitter_DataReceived;
    }

    private void Transmitter_DataReceived(object data)
    {
        // Display data.
        textBox1.Text = data.ToString();
    }
}

我们还需要一个发件人。单击按钮时,它会发送在文本框中输入的数据:

public partial class SendDataForm : Form
{
    public SendDataForm()
    {
        InitializeComponent();
    }

    private void SendDataButton_Click(object sender, EventArgs e)
    {
        Transmitter.TransmitData(dataTextBox.Text);
    }
}

测试程序同时打开两个窗口

static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        var sender = new SendDataForm();
        sender.Show();
        Application.Run(new ReceiveDataForm());
    }
}

当您在发送者表单中输入文本并单击按钮时,文本会自动显示在接收者表单中。

请注意,不需要GetData() 方法。由于事件处理程序private void Transmitter_DataReceived(object data) 通过object data 参数获取数据。

委托不是传输对象。根据Delegates (C# Programming Guide)

委托是一种表示对具有特定参数列表和返回类型的方法的引用的类型。

【讨论】:

    猜你喜欢
    • 2014-12-26
    • 1970-01-01
    • 2018-05-29
    • 2016-01-16
    • 1970-01-01
    • 2020-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多