来自 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(); };
sender
和 args
都被推断为该类型。它们不是 object
和 EventArgs
,正如您为 VB 代码假设的那样。这是 C# 代码如何成为垃圾的一个例子。
我有一个遗留解决方案,其中包含一些 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(); };
sender
和 args
都被推断为该类型。它们不是 object
和 EventArgs
,正如您为 VB 代码假设的那样。这是 C# 代码如何成为垃圾的一个例子。