在 C# 构造函数中处理可选委托的最佳方法是什么?
What is the best way to deal with optional delegates in a c# constructor?
我正在重构一个通过构造函数接收可选委托的函数。当在 class 内触发事件时,委托为 运行。如果未传递委托,则使用本地默认函数代替:
public class Foo
{
int _memberVariable;
readonly Action _onEventOne;
readonly Action _onEventTwo;
public Foo(Action onEventOne, Action onEventTwo = null)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo ?? DefaultEventTwo;
_onEventOne();
}
private void DefaultEventTwo()
{
++_memberVariable;
}
}
我想删除默认值(这是一个 public 接口,所以重载会更好),这是在生产代码中,所以我不想更改接口,除非我必须.
在理想情况下,我会使用构造函数链接:
public Foo(Action onEventOne) : this(onEventOne, DefaultEventTwo)
{
//CS0120 An object reference is required for the non-static field, method, or property 'Foo.DefaultEventTwo()
}
(我明白为什么这行不通,只是举例说明如果这不是构造函数我会使用的那种解决方案)。
因为委托是只读的,所以我不能在共享初始化类型函数中设置它们。
有没有比只传入 null 然后在主构造函数中捕获它更好的方法来处理这种情况?它感觉不是很优雅,我希望能够理想地捕获 null Action 作为异常(如果外部调用者使用 null 而不是使用重载的构造函数)。我可以从代表中删除只读,但再次感觉这不是一个很好的解决方案,因为它们真的是只读的。
如有任何想法,我们将不胜感激。
我能让它工作的唯一方法是让它工作起来丑陋(在我看来)。
您必须提供一个静态方法,但该静态方法可以使用对此的引用来获取实际方法。
这是我想出来的。
public Foo(Action onEventOne) : this(onEventOne, self => self.DefaultEventTwo)
{
//CS0120 An object reference is required for the non-static field, method, or property 'Foo.DefaultEventTwo()
}
public Foo(Action onEventOne, Action onEventTwo = null) : this(onEventOne, self => onEventTwo)
{ }
// private constructor, just for the sake of getting it working
private Foo(Action onEventOne, Func<Foo, Action> onEventTwo = null)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo(this); // <--
_onEventOne();
}
self => self.DefaultEventTwo
是获取动作的静态函数。该函数用于调用 onEventTwo(this)
以获取 this
实例的默认事件。
我错过了什么吗?
public class Foo
{
int _memberVariable;
readonly Action _onEventOne;
readonly Action _onEventTwo;
public Foo(Action onEventOne): this(onEventOne, null) { }
public Foo(Action onEventOne, Action onEventTwo)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo ?? DefaultEventTwo;
_onEventOne();
}
private void DefaultEventTwo()
{
++_memberVariable;
}
}
您所要做的就是删除默认值并创建一个只有一个参数的新构造函数。现在在最详细的构造函数(原始构造函数)中检查提供的值是否为 null
,如果是,则将 _onEventTwo
设置为 DefaultEventTwo
。
为避免任何人使用简化的构造函数,只需将其设为 internal
。
编辑:关于异常处理。如何使用内部构造函数作为 "main" - 所有其他构造函数都使用指示调用来源的参数调用:
internal Foo(Action onEventOne): this(onEventOne, null, true) { }
// public API: NULL not allwoed as param
public Foo(Action onEventOne, Action onEventTwo) : this(onEventOne, onEventTwo, false) { }
internal Foo(Action onEventOne, Action onEventTwo, bool internalUse)
{
_memberVariable = 0;
_onEventOne = onEventOne;
if(onEventTwo == null)
{
if(!internalUse) throw new ArgumentNullException("onEventTwo");
else this._onEventTwo = DefaultEventTwo;
}
_onEventOne();
}
我正在重构一个通过构造函数接收可选委托的函数。当在 class 内触发事件时,委托为 运行。如果未传递委托,则使用本地默认函数代替:
public class Foo
{
int _memberVariable;
readonly Action _onEventOne;
readonly Action _onEventTwo;
public Foo(Action onEventOne, Action onEventTwo = null)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo ?? DefaultEventTwo;
_onEventOne();
}
private void DefaultEventTwo()
{
++_memberVariable;
}
}
我想删除默认值(这是一个 public 接口,所以重载会更好),这是在生产代码中,所以我不想更改接口,除非我必须.
在理想情况下,我会使用构造函数链接:
public Foo(Action onEventOne) : this(onEventOne, DefaultEventTwo)
{
//CS0120 An object reference is required for the non-static field, method, or property 'Foo.DefaultEventTwo()
}
(我明白为什么这行不通,只是举例说明如果这不是构造函数我会使用的那种解决方案)。
因为委托是只读的,所以我不能在共享初始化类型函数中设置它们。
有没有比只传入 null 然后在主构造函数中捕获它更好的方法来处理这种情况?它感觉不是很优雅,我希望能够理想地捕获 null Action 作为异常(如果外部调用者使用 null 而不是使用重载的构造函数)。我可以从代表中删除只读,但再次感觉这不是一个很好的解决方案,因为它们真的是只读的。
如有任何想法,我们将不胜感激。
我能让它工作的唯一方法是让它工作起来丑陋(在我看来)。
您必须提供一个静态方法,但该静态方法可以使用对此的引用来获取实际方法。
这是我想出来的。
public Foo(Action onEventOne) : this(onEventOne, self => self.DefaultEventTwo)
{
//CS0120 An object reference is required for the non-static field, method, or property 'Foo.DefaultEventTwo()
}
public Foo(Action onEventOne, Action onEventTwo = null) : this(onEventOne, self => onEventTwo)
{ }
// private constructor, just for the sake of getting it working
private Foo(Action onEventOne, Func<Foo, Action> onEventTwo = null)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo(this); // <--
_onEventOne();
}
self => self.DefaultEventTwo
是获取动作的静态函数。该函数用于调用 onEventTwo(this)
以获取 this
实例的默认事件。
我错过了什么吗?
public class Foo
{
int _memberVariable;
readonly Action _onEventOne;
readonly Action _onEventTwo;
public Foo(Action onEventOne): this(onEventOne, null) { }
public Foo(Action onEventOne, Action onEventTwo)
{
_memberVariable = 0;
_onEventOne = onEventOne;
_onEventTwo = onEventTwo ?? DefaultEventTwo;
_onEventOne();
}
private void DefaultEventTwo()
{
++_memberVariable;
}
}
您所要做的就是删除默认值并创建一个只有一个参数的新构造函数。现在在最详细的构造函数(原始构造函数)中检查提供的值是否为 null
,如果是,则将 _onEventTwo
设置为 DefaultEventTwo
。
为避免任何人使用简化的构造函数,只需将其设为 internal
。
编辑:关于异常处理。如何使用内部构造函数作为 "main" - 所有其他构造函数都使用指示调用来源的参数调用:
internal Foo(Action onEventOne): this(onEventOne, null, true) { }
// public API: NULL not allwoed as param
public Foo(Action onEventOne, Action onEventTwo) : this(onEventOne, onEventTwo, false) { }
internal Foo(Action onEventOne, Action onEventTwo, bool internalUse)
{
_memberVariable = 0;
_onEventOne = onEventOne;
if(onEventTwo == null)
{
if(!internalUse) throw new ArgumentNullException("onEventTwo");
else this._onEventTwo = DefaultEventTwo;
}
_onEventOne();
}