[CallerLineNumber]
是一个很棒的语言功能。但是我将它用于automatically order class properties as their declaration order。但是,当用户使用此参数调用函数或构造函数时,用户可以向其提供值,这完全胜过自动生成的目的。目前,我必须将此参数命名为_doNotSet
,作为调用者不设置此参数的提示。
如何强制它只读,甚至更好,将其隐藏在功能签名中?
另一个想法是将参数标记为[Obsolete]
所以通过使用它,编译器会发出警告。不幸的是,ObsoleteAttribute
并非针对参数,因此我无法将参数标记为。
答案 0 :(得分:2)
我很惊讶编译器没有覆盖调用函数传入的值。无论如何,接受这种不幸的行为,我不认为你可以做任何事情保证没有人会破坏它。
据我所知,你最接近的就是你所做的。将其命名为_doNotSet
,但我建议使用_settingThisBreaksTheTool
之类的东西。根据代码的受众,这可能足以满足您的需求。
编辑:此link显示如何确定是否提供了值,遗憾的是,这里提供的任何策略都不适合您。基本上他们建议使用已知的不太可能的值(在您的情况下不可能,因为您不知道行号或您不在乎)。或不使用默认值并重载该功能。但是[CallerLineNumber]
属性需要该参数是可选的。开溜。
来吧微软......为什么
这将介绍.Net如何实现可选参数的默认值。如果在函数上指定参数是可选的,并且在没有值的情况下调用该函数,则在编译期间会发生一些非常特殊的事情。 不具有该参数值的代码将替换为具有值的代码,即默认值。
我前一段时间阅读了一些博客文章,this是最简单的理解基础知识。
我可能会在这里进行一些跳转,但我的猜测是[CallerLineNumber]
属性表示编译器使用不同的值,即行号。 但是编译器甚至不会通过注入值的过程,因为首先存在一个值。
微软可能希望[CallerLineNumber]
覆盖传递给函数的值,但是搭载默认值的副作用可能导致它们无法支持。我将很有兴趣看看Roslyn项目是否为该功能带来了一些增强功能。
答案 1 :(得分:0)
您可以创建类似ICallerLineNumberPlaceholder
的界面。
public Task<TResult> ExecuteWithArgs<TResult, TParam>(Func<IDBLambdaEngine, TResult> queryExpression, TParam param, ICallerLineNumberPlaceholder placeholder = default, [CallerLineNumber] int callerLineNumber = 0) where TResult : new()
{
return InternalExecute<TResult, TParam>(callerLineNumber, param);
}