Operator '?' cannot be applied to operand of type 'method group'(运算符“?”不能应用于类型为“方法组”的操作数)

7 浏览
0 Comments

Operator '?' cannot be applied to operand of type 'method group'(运算符“?”不能应用于类型为“方法组”的操作数)

这是关于C#新引入的空检查运算符的问题。

假设我有一个接口:

interface ILogger
{
    void Log(string message);
}

还有一个期望一个日志动作的函数:

void DoWork(Action logAction)
{
    // 做工作并使用 @logAction
}

为什么如果我尝试写以下代码会得到以下编译器错误:

void Main(string[] args)
{
    ILogger logger = GetLogger(); // 假设GetLogger()可能返回null
    //
    // 编译器错误:
    // 运算符'?'不能应用于'type method group'的操作数
    //
    DoWork(logger?.Log);   
}

0
0 Comments

问题的出现原因是,?.操作符与?:操作符的工作方式是相同的。例如,logger?.Loglogger == null ? null : logger.Log得到的结果是相同的,只是logger只会被计算一次。

问题在于,在早期版本的C#中,logger == null ? null : logger.Log同样是无效的。?:要求其中一个操作数可以转换为另一个操作数的类型,但是nulllogger.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#中同样存在,没有一个简单的优雅的解决方法。

0
0 Comments

在上述代码中,出现了"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'"的问题。

0
0 Comments

问题的出现原因是在使用 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' 这个问题的出现原因和解决方法的整理。

0