如何强制参数[CallerLineNumber]只读?

时间:2014-06-21 02:39:16

标签: c# .net

[CallerLineNumber]是一个很棒的语言功能。但是我将它用于automatically order class properties as their declaration order。但是,当用户使用此参数调用函数或构造函数时,用户可以向其提供值,这完全胜过自动生成的目的。目前,我必须将此参数命名为_doNotSet,作为调用者不设置此参数的提示。

如何强制它只读,甚至更好,将其隐藏在功能签名中?

另一个想法是将参数标记为[Obsolete]所以通过使用它,编译器会发出警告。不幸的是,ObsoleteAttribute并非针对参数,因此我无法将参数标记为。

2 个答案:

答案 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);
}