Оператор?"не может быть применен к операнду типа "группа методов"
это вопрос о недавно введенном операторе нулевой проверки C#.
предполагая, что у меня есть интерфейс, такой как:
interface ILogger
{
void Log(string message);
}
и функция, которая ожидает действия ведения журнала:
void DoWork(Action<string> logAction)
{
// Do work and use @logAction
}
почему я получаю следующую ошибку компилятора, если я пытаюсь написать:
void Main(string[] args)
{
ILogger logger = GetLogger(); // Assume GetLogger() may return null
//
// Compiler error:
// Operator '?' cannot be applied to operand of type 'method group'
//
DoWork(logger?.Log);
}
3 ответов
ничего особенного не происходит с ?.
здесь он работает так же, как и с ?:
: logger?.Log
даст тот же результат, что и logger == null ? null : logger.Log
, за исключением logger
оценивается только один раз.
проблема в том, что logger == null ? null : logger.Log
также недействителен в более ранних версиях C#. ?:
требует, чтобы один операнд был конвертируемым в тип другого, но ни null
, ни logger.Log
тип. Вы должны написать это, например,logger == null ? null : (Action<string>) logger.Log
.
к сожалению, введение этого приведения означает, что нет простой довольно сокращенной версии C# 6, которую вы можете использовать, так как то же самое относится к ?.
: logger?.Log
является недействительным, поскольку logger.Log
не имеет типа, так что logger?.Log
также не имеет типа, но если это выражение Без типа, и это не группа методов, то C# ничего не позволит вам сделать с ним.
Если вы можете изменить свой интерфейс на
interface ILogger
{
//void Log(string message);
Action<string> Log {get; }
}
тогда вы можете использовать logger?.Log
нотации.
реализация ILogger будет выглядеть примерно так:
class Logger : ILogger
{
Action<string> Log => str => { /* Do stuff with str */ };
}
добавление к заявлению @hvd
мы также можем использовать Нулевой Условный Оператор ( ?. ) С Нуль-Коалесцирующий Оператор ( ?? ) Если вы пишете следующий код
string userName = null;
int len = userName.Length;
затем
userName.Length
выдаст исключение: "необработанное исключение типа" System.NullReferenceException ' произошло в ConsoleApplication... Дополнительные сведения: ссылка на объект не указывает на экземпляр объекта."
если вы используете следующий код
string userName = null;
int? len = userName.Length;
все равно вы получите то же исключение
но
int? len = userName?.Length;
он вернет null и не будет выбрасывать исключение
но у нас все еще есть проблема. Проблема в том, что я использую int? (Nullable int), что нехорошо, потому что люди предпочтут, чтобы если строка равна null, то она должна возвращать 0.
таким образом, мы можем сделать это с помощью комбинации нулевого условного оператора(?.) и null-coalescing Оператор (??)
int len = userName?.Length ?? 0;
добавил
у нас есть еще одно использование нулевого условного оператора.
как при работе с обработкой событий в этом случае мы можем использовать
myCustomEventHandler?.Вызов(это, EventArgs в.Пусто);
где "myCustomEventHandler" является публичным событием перед C#6.0 мы должны создать локальную копию "myCustomEventHandler", иначе он может вызвать исключение в случае muti-threaded приложение. в то время как в C# 6 мы можем напрямую вызвать "myCustomEventHandler" без создания локальной копии, и это потокобезопасно.
например, в C# 5
var handler= this.myCustomEventHandler;
if (handler!= null)
handler(…)
в C# 6
myCustomEventHandler?.Invoke(e)