Возможные ловушки использования этого (дополнительный базирующийся метод) стенография

15
задан Keith 15 June 2015 в 06:39
поделиться

10 ответов

Мы независимо придумали то же самое дополнительное имя метода и реализацию: Распространяющий пустой указатель дополнительный метод . Таким образом, мы не думаем, что это сбивает с толку или злоупотребление дополнительными методами.

я записал бы Ваши "несколько уровней" пример с объединением в цепочку следующим образом:

propertyValue1 = myObject.IfNotNull(o => o.ObjectProp).IfNotNull(p => p.StringProperty);

существует теперь закрытая ошибка на Microsoft Connect предложенный"? ". как новый оператор C#, который выполнил бы это пустое распространение. Mads Torgersen (от команды языка C#) кратко объяснил, почему они не реализуют ее.

16
ответ дан 1 December 2019 в 00:08
поделиться

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

11
ответ дан 1 December 2019 в 00:08
поделиться

Вот другое решение, для цепочечных участников, включая дополнительные методы:

public static U PropagateNulls<T,U> ( this T obj
                                     ,Expression<Func<T,U>> expr) 
{  if (obj==null) return default(U);

   //uses a stack to reverse Member1(Member2(obj)) to obj.Member1.Member2 
   var members = new Stack<MemberInfo>();

   bool       searchingForMembers = true;
   Expression currentExpression   = expr.Body;

   while (searchingForMembers) switch (currentExpression.NodeType)
    { case ExpressionType.Parameter: searchingForMembers = false; break;

           case ExpressionType.MemberAccess:    
           { var ma= (MemberExpression) currentExpression;
             members.Push(ma.Member);
             currentExpression = ma.Expression;         
           } break;     

          case ExpressionType.Call:
          { var mc = (MethodCallExpression) currentExpression;
            members.Push(mc.Method);

           //only supports 1-arg static methods and 0-arg instance methods
           if (   (mc.Method.IsStatic && mc.Arguments.Count == 1) 
               || (mc.Arguments.Count == 0))
            { currentExpression = mc.Method.IsStatic ? mc.Arguments[0]
                                                     : mc.Object; 
              break;
            }

           throw new NotSupportedException(mc.Method+" is not supported");
         } 

        default: throw new NotSupportedException
                        (currentExpression.GetType()+" not supported");
  }

   object currValue = obj;
   while(members.Count > 0)
    { var m = members.Pop();

      switch(m.MemberType)
       { case MemberTypes.Field:
           currValue = ((FieldInfo) m).GetValue(currValue); 
           break;

         case MemberTypes.Method:
           var method = (MethodBase) m;
           currValue = method.IsStatic
                              ? method.Invoke(null,new[]{currValue})
                              : method.Invoke(currValue,null); 
           break;

         case MemberTypes.Property:
           var method = ((PropertyInfo) m).GetGetMethod(true);
                currValue = method.Invoke(currValue,null);
           break;

       }     

      if (currValue==null) return default(U);   
    }

   return (U) currValue;    
}

Затем можно сделать это, где любой может быть пустым, или ни один:

foo.PropagateNulls(x => x.ExtensionMethod().Property.Field.Method());
15
ответ дан 1 December 2019 в 00:08
поделиться

Как

propertyValue1 = myObject.IfNotNull(o => o.ObjectProp.IfNotNull( p => p.StringProperty ) );

легче читать и записать, чем

if(myObject != null && myObject.ObjectProp != null)
    propertyValue1 = myObject.ObjectProp.StringProperty;

, Jafar Husain отправил образец использования Деревьев выражений для проверки на пустой указатель в цепочке, макросы Во время выполнения в C# 3.

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

5
ответ дан 1 December 2019 в 00:08
поделиться

Я просто должен сказать, что люблю этот взлом!

я не понял, что дополнительные методы не подразумевают пустую проверку, но она полностью имеет смысл. Как James указал, сам дополнительный вызов метода не является больше дорогим, чем нормальный метод, однако при выполнении тонны этого затем действительно имеет смысл следовать за Шаблоном Несуществующего объекта, это предложенный ljorquera. Или использовать несуществующий объект и?? вместе.

class Class1
{
    public static readonly Class1 Empty = new Class1();
.
.
x = (obj1 ?? Class1.Empty).X;
5
ответ дан 1 December 2019 в 00:08
поделиться

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


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

"Util". решетки, но IMO меньшее синтаксическое зло.

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

1
ответ дан 1 December 2019 в 00:08
поделиться

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

Примечание, кроме которого Вы ничего на самом деле не расширяете (теоретически).

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

сгенерирует код IL точно, как будто он был записан:

ExtentionClass::IfNotNull(myObject2,  x => x.IntProperty, 0);

нет никаких "издержек", добавленных к объектам поддерживать это.

1
ответ дан 1 December 2019 в 00:08
поделиться

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

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

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

0
ответ дан 1 December 2019 в 00:08
поделиться

В то время как дополнительные методы обычно вызывают недоразумения при вызове от пустых экземпляров я думаю, что намерение довольно просто в этом случае.

string x = null;
int len = x.IfNotNull(y => y.Length, 0);

я хотел бы быть уверенным этот статический метод работы над Типами Значения, которые могут быть пустыми, такими как интервал?

Редактирование: в компиляторе говорится, что ни один из них не допустим:

    public void Test()
    {
        int? x = null;
        int a = x.IfNotNull(z => z.Value + 1, 3);
        int b = x.IfNotNull(z => z.Value + 1);
    }

Кроме этого, пойдите для него.

1
ответ дан 1 December 2019 в 00:08
поделиться

Вот еще одно решение, использующее myObject.NullSafe (x => x.SomeProperty.NullSafe (x => x.SomeMethod)), объясненное на http://www.epitka.blogspot.com/

0
ответ дан 1 December 2019 в 00:08
поделиться
Другие вопросы по тегам:

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