вызывая trygetmember на цепочечных нулевых ссылках - PullRequest
0 голосов
/ 22 октября 2010

Возможно ли иметь реализацию DynamicObject, которую можно вызывать в цепочке, сохраняя нулевую ссылку до конца, если где-либо в пути встречается нулевая ссылка, без каких-либо исключений?

a.b.c.e

например: если a равно нулю, то a.b.c.e равно нулю, или если c равно нулю, c.e равно нулю и т. Д .?

Очень похоже на монаду Maybe из Хаскелла.

Ответы [ 3 ]

1 голос
/ 23 октября 2010

Проверьте эту замечательную статью: Цепные нулевые проверки и монада Maybe

Очень многие программисты сталкивались с ситуацией, когда при доступе к свойству вложенного объекта (например, person).Address.PostCode), они должны сделать несколько нулевых проверок.Это требование часто появляется при синтаксическом анализе XML, когда отсутствующие элементы и атрибуты могут возвращать значение NULL при попытке доступа к ним (и впоследствии при попытке доступа к Value генерируется исключение NullReferenceException).В этой статье я покажу, как использование монады Maybe в C # в сочетании с использованием методов расширения может использоваться для улучшения читабельности.

1 голос
/ 14 августа 2011

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

https://gist.github.com/1030887

public static class Extensions
{
    public static TResult SafeInvoke<TModel, TResult>(this TModel model, Func<TModel, TResult> expression, TResult nullValue = default(TResult))
    {
        try
        {
            return expression(model);
        }
        catch (NullReferenceException)
        {
            return nullValue;
        }
    }
}

Вы можете вызывать код справедливолегко.

public class MyModel
{
  public Name Name { get; set; }
}

public class Name
{
  public string First { get; set; }
  public string Last { get; set; }
}

var model = new MyModel();
var firstName = model.SafeInvoke(x => x.Name.First, "john");
var lastName = model.SafeInvoke(x => x.Name.Last, "doe");

Console.WriteLine("{0}, {1}", lastName, firstName)
// prints: "doe, john"
1 голос
/ 22 октября 2010

Вы можете сделать что-то подобное, но не для самого внешнего объекта, т. Е. Если a равно нулю, вы не можете получить доступ к a.b.

Вы можете создать пустой экземпляр A класс, который возвращает пустые экземпляры для всех своих свойств.Тогда a.b вернет пустой экземпляр B, который для свойства c вернет пустой экземпляр C, который для свойства e вернет пустой экземпляр E.

Вы не получите нулевое значение, но вы получите пустой экземпляр, который вы можете проверить с помощью:

E e = a.b.c.e;
if (e != E.Empty) { ... }

Если какое-либо из свойств по пути возвращает пустой экземпляр, конецрезультат будет E.Empty.

public class A {

  public B b;

  public A(B newB) { b = newB; }

  private static A _empty = new A(B.Empty);
  public static A Empty { get { return _empty; }}

}

public class B {

  public C c;

  public B(C newC) { c = newC; }

  private static B _empty = new B(C.Empty);
  public static B Empty { get { return _empty; } }

}

public class C {

  public E e;

  public C(E newE) { e = newE; }

  private static C _empty = new C(E.Empty);
  public static C Empty { get { return _empty; } }

}

public class E {

  public string name;

  public E(string newName) { name = newName; }

  private static E _empty = new E(null);
  public static E Empty { get { return _empty; } }

}

Пример:

A a1 = new A(new B(new C(new E("Hello world!"))));
A a2 = new A(new B(new C(E.Empty)));
A a3 = new A(B.Empty);

E e1 = a1.b.c.e; // e1.name returns "Hello world!"
E e2 = a2.b.c.e; // e2 == E.Empty
E e3 = a3.b.c.e; // e3 == E.Empty
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...