Возможные ловушки использования этого (основанного на методе расширения) сокращения - PullRequest
15 голосов
/ 23 сентября 2008

Обновление C # 6

In C # 6 ?. теперь является языковой функцией :

// C#1-5
propertyValue1 = myObject != null ? myObject.StringProperty : null; 

// C#6
propertyValue1 = myObject?.StringProperty;

Приведенный ниже вопрос по-прежнему относится к более старым версиям, но если разработка нового приложения с использованием нового оператора ?. является гораздо более эффективной практикой.

Оригинальный вопрос:

Я регулярно хочу получить доступ к свойствам на возможно нулевых объектах:

string propertyValue1 = null;
if( myObject1 != null )
    propertyValue1 = myObject1.StringProperty;

int propertyValue2 = 0;
if( myObject2 != null )
    propertyValue2 = myObject2.IntProperty;

И так далее ...

Я использую это так часто, что у меня есть фрагмент для этого.

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

propertyValue1 = myObject != null ? myObject.StringProperty : null;

Однако это немного неуклюже, особенно если задано много свойств или если несколько уровней могут быть нулевыми, например:

propertyValue1 = myObject != null ? 
    (myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null : null;

Что мне действительно нужно, так это синтаксис стиля ??, который отлично работает для напрямую нулевых типов:

int? i = SomeFunctionWhichMightReturnNull();
propertyValue2 = i ?? 0;

Итак, я придумал следующее:

public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action, TResult valueIfNull )
    where T : class
{
    if ( input != null ) return action( input );
    else return valueIfNull;
}

//lets us have a null default if the type is nullable
public static TResult IfNotNull<T, TResult>( this T input, Func<T, TResult> action )
    where T : class
    where TResult : class
{ return input.IfNotNull( action, null ); }

Это позволяет мне использовать следующий синтаксис:

propertyValue1 = myObject1.IfNotNull( x => x.StringProperty );
propertyValue2 = myObject2.IfNotNull( x => x.IntProperty, 0);

//or one with multiple levels
propertyValue1 = myObject.IfNotNull( 
    o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );

Это упрощает эти вызовы, но я не уверен насчет включения такого рода метода расширения - он делает код немного легче для чтения, но за счет расширения объекта. Это могло бы появиться во всем, хотя я мог бы поместить его в специально указанное пространство имен.

Этот пример является довольно простым, чуть более сложным будет сравнение двух обнуляемых свойств объекта:

if( ( obj1 == null && obj2 == null ) || 
    ( obj1 != null && obj2 != null && obj1.Property == obj2.Property ) )
    ...

//becomes
if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property ) 
    ...

Каковы подводные камни при использовании расширений таким образом? Другие кодеры могут быть сбиты с толку? Это просто злоупотребление расширениями?


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

propertyValue1 = myObject != null ? myObject.StringProperty : null;

//becomes
propertyValue1 = myObject?StringProperty;

Это значительно упростит сложный случай:

propertyValue1 = myObject != null ? 
    (myObject.ObjectProp != null ? myObject.ObjectProp.StringProperty) : null

//becomes
propertyValue1 = myObject?ObjectProp?StringProperty;

Это будет работать только для типов значений, но вы можете вернуть обнуляемые эквиваленты:

int? propertyValue2 = myObject?ObjectProp?IntProperty;

//or

int propertyValue3 = myObject?ObjectProp?IntProperty ?? 0;

Ответы [ 11 ]

0 голосов
/ 23 сентября 2008

Лично, даже после всех ваших объяснений, я не могу вспомнить, как, черт возьми, это работает:

if( obj1.NullCompare( obj2, (x,y) => x.Property == y.Property ) 

Это может быть потому, что у меня нет опыта C #; Тем не менее, я мог читать и понимать все остальное в вашем коде. Я предпочитаю сохранять независимость от языка кода (особенно для тривиальных вещей), чтобы завтра другой разработчик мог изменить его на совершенно новый язык без лишней информации о существующем языке.

...