Operator '?' cannot be applied to operand of type 'method group'(运算符“?”不能应用于类型为“方法组”的操作数)
Operator '?' cannot be applied to operand of type 'method group'(运算符“?”不能应用于类型为“方法组”的操作数)
这是关于C#新引入的空检查运算符的问题。
假设我有一个接口:
interface ILogger { void Log(string message); }
还有一个期望一个日志动作的函数:
void DoWork(ActionlogAction) { // 做工作并使用 @logAction }
为什么如果我尝试写以下代码会得到以下编译器错误:
void Main(string[] args) { ILogger logger = GetLogger(); // 假设GetLogger()可能返回null // // 编译器错误: // 运算符'?'不能应用于'type method group'的操作数 // DoWork(logger?.Log); }
问题的出现原因是,?.
操作符与?:
操作符的工作方式是相同的。例如,logger?.Log
与logger == null ? null : logger.Log
得到的结果是相同的,只是logger
只会被计算一次。
问题在于,在早期版本的C#中,logger == null ? null : logger.Log
同样是无效的。?:
要求其中一个操作数可以转换为另一个操作数的类型,但是null
和logger.Log
都没有类型。你需要将其写为logger == null ? null : (Action<string>) logger.Log
。
不幸的是,引入了这样的转换意味着在C# 6中没有简单的优雅的写法可供使用,因为对?.
同样适用:由于logger.Log
没有类型,所以logger?.Log
也没有类型。如果它是一个没有类型的表达式,并且它不是一个方法组,那么在C#中就没有什么可以使用它的方法。
问题的解决方法是将logger?.Log
改为logger == null ? null : (Action<string>) logger.Log
。
,?.
操作符和?:
操作符的工作方式相同,但是?.
操作符在处理方法组时需要进行类型转换。这个问题在早期版本的C#中同样存在,没有一个简单的优雅的解决方法。
在上述代码中,出现了"Operator '?' cannot be applied to operand of type 'method group'"的问题。这个问题的出现是因为在使用logger?.Log
时,接口ILogger中的Log属性被定义为一个方法组,而不是一个具体的方法。所以,编译器无法对这个方法组应用"?"操作符。
为了解决这个问题,可以将接口ILogger的Log属性改为一个委托类型的属性,如下所示:
interface ILogger { Action<string> Log {get; } }
然后,ILogger的实现类Logger中的Log属性应该被赋值为一个具体的方法,如下所示:
class Logger : ILogger { Action<string> Log => str => { /* Do stuff with str */ }; }
通过这种方式,将Log属性定义为一个委托类型,就可以在使用logger?.Log
时避免出现"Operator '?' cannot be applied to operand of type 'method group'"的问题。
问题的出现原因是在使用 Null Conditional Operator ( ?. ) 时,对于类型为方法组的操作数,无法应用操作符 '?'。解决方法是使用 null-coalescing Operator (??) 来提供一个默认值。
在示例中,如果直接使用代码 `string userName = null; int len = userName.Length;` 则会抛出异常 "An unhandled exception of type 'System.NullReferenceException' occurred in ConsoleApplication... Additional information: Object reference not set to an instance of an object."。但是使用代码 `int? len = userName?.Length;` 则不会抛出异常,而是返回 null。
然而,使用 int? (Nullable int) 类型仍然存在问题,因为人们更希望如果字符串为 null,则返回 0。因此,可以通过使用 null Conditional Operator(?.) 和 null-coalescing Operator(??) 的组合来解决这个问题,代码如下:
int len = userName?.Length ?? 0;
此外,null conditional operator 还可以在处理事件时使用。在 C# 6.0 之前,需要创建 "myCustomEventHandler" 的本地副本,否则在多线程应用程序中可能会抛出异常。而在 C# 6 中,可以直接调用 "myCustomEventHandler" 而不需要创建本地副本,因为它是线程安全的。示例如下:
在 C# 5 中:
var handler = this.myCustomEventHandler; if (handler != null) handler(…)
在 C# 6 中:
myCustomEventHandler?.Invoke(e)
以上就是 Operator '?' cannot be applied to operand of type 'method group' 这个问题的出现原因和解决方法的整理。