来自 VB.NET 的 C# 委托

C# Delegate from VB.NET

我有一个遗留解决方案,其中包含一些 C# 项目(最新的)和一些 VB 项目(最旧的)。我知道这不是一个好的做法,但这是我现在的情况,所以我必须处理它。

在 C# 项目中,我有一些这样的代码:

public class MyObjectClass 
{
    ... more code here ...
    public delegate void SelectedItemChange(IMyInterface oldItem, IMyInterface newItem);
    public virtual SelectedItemChange SelectedItemChanged { get; set; }
}

当我以这种方式从另一个 C# 项目中使用它时,这就像一个魅力:

public class MySecondaryClass
{
    ... more code here ...
    MyObjectClass MyObject = new();
    MyObject.SelectedItemChanged += (sender, args) => { DoSomething(); };
}

到目前为止,还不错。问题是当我必须使用来自 VB.NET 项目的同一个委托时。我试过这个:

Public Class MySecondaryClassVB
   ... more code here ...
   Dim MyObject as MyObjectClass = New MyObjectClass()
   AddHandler MyObject.SelectedItemChanged, Sub(sender As Object, args As EventArgs)
                                                 DoSomething()
                                            End Sub
End Class

但是 SelectedItemChanged 出现在 Visual Studio 中,下划线为红色,下一个错误是:

'SelectedItemChanged' is not an event of 'MyObjectClass'

我无法理解为什么它在 C# 中工作而不在 VB.NET 中工作,所以我猜我的 AddHandler 语法不正确。正确的语法是什么?我做错了什么?

谢谢

更新: 也许对理解问题很有用。真正的 MyObjectClass 在那里我发出了事件:

public class MyObjectClass 
{
    ... more code here ...

    private IMyInterface _selectedItem;
    public IMyInterface SelectedItem
    {
        get => _selectedItem;
        set
        {
            IMyInterface oldSelectedItem = _selectedItem;
            _selectedItem = value;
            SelectedItemChanged?.Invoke(oldSelectedItem, _selectedItem);
            SetProperty(ref _selectedItem, value);
        }
    }

    public delegate void SelectedItemChange(IMyInterface oldItem, IMyInterface newItem);
    public virtual SelectedItemChange SelectedItemChanged { get; set; }
}

然后我想从 C# 项目(我可以毫无问题地完成)或 VB.NET 项目(我无法订阅)订阅该事件。

这是因为 SelectedItemChange 不是一个事件。您需要将其声明为 event

public event SelectedItemChange SelectedItemChange_Event;

您在 VB 中的 AddHanler 语法是正确的

试试这个:

Public Event SelectedItemChange_Event As SelectedItemChange

如果那个 SelectedItemChanged 只会引用一个委托,那么只需创建一个并分配它,就像您对任何其他 属性 引用任何其他对象所做的那样:

MyObject.SelectedItemChanged = New SelectedItemChange(Sub(sender, args) DoSomething())

如果它可能引用多个委托,那么您可以明确地执行 C# += 运算符隐式执行的操作:

MyObject.SelectedItemChanged = [Delegate].Combine(MyObject.SelectedItemChanged, New SelectedItemChange(Sub(sender, args) DoSomething()))

这里值得注意的是,您的委托是使用 IMyInterface 类型的两个参数进行特定声明的。这意味着,在这段代码中:

MyObject.SelectedItemChanged += (sender, args) => { DoSomething(); };

senderargs 都被推断为该类型。它们不是 objectEventArgs,正如您为 VB 代码假设的那样。这是 C# 代码如何成为垃圾的一个例子。