Действительно ли возможно использовать оператор?? и выдайте новое Исключение ()?

C#: LINQ

var str = "a b a";
var test = Enumerable.SequenceEqual(str.ToCharArray(), 
           str.ToCharArray().Reverse());
28
задан user1069816 22 March 2018 в 18:28
поделиться

5 ответов

Для C # 7

В C # 7 throw становится выражением, поэтому можно использовать именно тот код, который описан в вопросе.

Для C # 6 и ранее

Вы не можете сделать это напрямую в C # 6 и ранее - второй операнд ?? должно быть выражением, а не оператором throw.

Есть несколько альтернатив, если вы действительно просто пытаетесь найти краткий вариант:

Вы можете написать:

public static T ThrowException<T>()
{
    throw new Exception(); // Could pass this in
}

А затем:

return command.ExecuteScalar() as int? ?? ThrowException<int?>();

Я действительно не рекомендую вам делать это, хотя ... это довольно ужасно и неидиоматично.

Как насчет метода расширения:

public static T ThrowIfNull(this T value)
{
    if (value == null)
    {
        throw new Exception(); // Use a better exception of course
    }
    return value;
}

Затем:

return (command.ExecuteScalar() as int?).ThrowIfNull();

Еще одна альтернатива (снова расширение метод):

public static T? CastOrThrow<T>(this object x) 
    where T : struct
{
    T? ret = x as T?;
    if (ret == null)
    {
        throw new Exception(); // Again, get a better exception
    }
    return ret;
}

Вызов с помощью:

return command.ExecuteScalar().CastOrThrow<int>();

Это несколько некрасиво, потому что вы не можете указать int? в качестве аргумента типа ...

54
ответ дан 28 November 2019 в 02:44
поделиться

Как уже было сказано, вы не можете сделать это с помощью ?? оператор (ну, не без некоторых искажений, которые, кажется, не подходят для вашей цели создания этого очистителя).

Когда я вижу, как появляется этот шаблон, я сразу думаю о Enforcements . Первоначально из мира C ++ они довольно хорошо переносятся на C #, хотя, возможно, в большинстве случаев они менее важны.

Идея состоит в том, что вы берете что-то в форме:

if( condition )
{
  throw Exception;
}

и преобразуете его в:

Enforce<Exception>( condition );

(вы можете дополнительно упростить, установив тип исключения по умолчанию).

В дальнейшем вы можете написать набор методов в стиле Nunit для различных проверок условий, например,

Enforce<Exception>.NotNull( obj );
Enforce<Exception>.Equal( actual, expected );
Enforce<Exception>.NotEqual( actual, expected );

и т. д.

Или, что еще лучше, предоставив лямбу ожидания:

Enforce<Exception>( actual, expectation );

Что действительно здорово, так это то, что как только вы это сделаете, вы можете вернуть фактический параметр и применить inline :

return Enforce( command.ExecuteScalar() as Int32?, (o) => o.HasValue ).Value;

... и это похоже на то, что вам нужно.

Я постучал. до реализации этого раньше. Есть пара мелких проблем, например, как вы в общем случае создаете объект исключения, который принимает аргументы - некоторые варианты там (я выбрал отражение в то время, но передача фабрики в качестве дополнительного параметра может быть даже лучше). Но в целом все довольно просто и может действительно очистить много кода.

Это в моем списке вещей, которые нужно сделать, чтобы создать реализацию с открытым исходным кодом.

например, как вы в общем создаете объект исключения, который принимает аргументы - некоторые варианты там (я выбрал отражение в то время, но передача фабрики в качестве дополнительного параметра может быть даже лучше). Но в целом все довольно просто и может действительно очистить много кода.

Это в моем списке вещей, которые необходимо сделать, чтобы создать реализацию с открытым исходным кодом.

например, как вы обычно создаете объект исключения, который принимает аргументы - некоторые варианты там (я выбрал отражение в то время, но передача фабрики в качестве дополнительного параметра может быть даже лучше). Но в целом все довольно просто и может действительно очистить много кода.

Это в моем списке вещей, которые нужно сделать, чтобы создать реализацию с открытым исходным кодом.

9
ответ дан 28 November 2019 в 02:44
поделиться

Если вам просто нужно исключение, когда возвращаемое значение не является Int32 , сделайте следующее:

return (int)command.ExecuteScalar();

Если вы хотите создать собственное исключение, тогда я d, вероятно, вместо этого сделайте что-то вроде этого:

int? result = command.ExecuteScalar() as int?;
if (result == null) throw new YourCustomException();
return result.Value;
4
ответ дан 28 November 2019 в 02:44
поделиться

Вы не сможете генерировать исключение в правой части оператора объединения с нулевым значением. Причина в том, что правая часть оператора должна быть выражением, а не утверждением.

Оператор объединения с нулевым значением работает следующим образом: если левое значение оператора равно нулю, вернуть его; в противном случае верните то, что находится справа от оператора. Ключевое слово throw не возвращает значения; следовательно, его нельзя использовать в правой части оператора.

2
ответ дан 28 November 2019 в 02:44
поделиться

Причина, по которой вы не можете этого сделать:

return command.ExecuteScalar() as Int32? ?? throw new Exception();

Это потому, что генерирование исключения - это оператор, а не выражение.

Если вы просто хотите немного сократить код , возможно это:

var result = command.ExecuteScalar() as Int32?;
if(result.HasValue) return result;
throw new Exception();

В остальном нет необходимости.

1
ответ дан 28 November 2019 в 02:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: