От: | Alexander Polyakov | ||
Дата: | 09.09.10 15:26 | ||
Оценка: | 25 (3) +1 |
string someMethodResult = new SomeClass1().SomeMethod1();
Сделаем обычный Extract Method:string someMethodResult = ExtractedMethod1().SomeMethod1();
SomeClass1 ExtractedMethod1()
{
return new SomeClass1();
}
string someMethodResult = null.SomeMethod1(); //ошибка компиляции
Во втором варианте получаем ошибку в run time-е:string someMethodResult = ExtractedMethod1().SomeMethod1(); //ошибка в run time-е
SomeClass1 ExtractedMethod1()
{
return null;
}
string someMethodResult = OptionalValue.Nothing<SomeClass1>().Process(
value => value.SomeMethod1(),
() => "[Экземпляр класса SomeClass1 не существует]");
второй вариант:string someMethodResult = ExtractedMethod1().Process(
value => value.SomeMethod1(),
() => "[Экземпляр класса SomeClass1 не существует]");
IOptionalValue<SomeClass1> ExtractedMethod1()
{
return OptionalValue.Nothing<SomeClass1>();
}
Таким образом, оба варианта ведут себя одинаково -- если код компилируется, то он работает.I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time ...
http://en.wikipedia.org/wiki/C._A._R._Hoare
A more elegant solution that will never come true is to apply value type syntax for reference types: all references are implicitly not nulls for the compiler, but a question mark after a type (ie: «string?» or «Customer?») allows you to set null to the variable.
http://codevanced.net/post/One-Annotations-Way-Resharper.aspx
1.0 Non-Null Types Many errors in modern programs manifest themselves as null-dereference errors, suggesting the importance of a programming language providing the ability to discriminate between expressions that may evaluate to null and those that are sure not to (for some experimental evidence, see [24, 22]). In fact, we would like to eradicate all null dereference errors.
http://stackoverflow.com/questions/1943465/avoiding-null-reference-exceptions
public interface IOptionalValue<out TValue>
{
TResult Process<TResult>(Func<TValue, TResult> existFunc, Func<TResult> notExistFunc);
}
public static class OptionalValue
{
public static IOptionalValue<TValue> Nothing<TValue>()
{
return NotExistOptionalValue<TValue>.Instance;
}
public static IOptionalValue<TValue> AsOptionalValue<TValue>(
this TValue value)
{
return new ExistOptionalValue<TValue>(value);
}
public static IOptionalValue<TTarget> ProcessValue<TValue, TTarget>(
this IOptionalValue<TValue> optionalValue,
Func<TValue, TTarget> func)
{
return optionalValue.ProcessValue(value => func(value).AsOptionalValue());
}
public static IOptionalValue<TTarget> ProcessValue<TValue, TTarget>(
this IOptionalValue<TValue> optionalValue,
Func<TValue, IOptionalValue<TTarget>> func)
{
return optionalValue.Process(func, Nothing<TTarget>);
}
public static void Process<TValue>(
this IOptionalValue<TValue> optionalValue,
Action<TValue> existAction,
Action notExistAction)
{
optionalValue.Process(existAction.ToFunc(), notExistAction.ToFunc());
}
public static void ProcessValue<TValue>(
this IOptionalValue<TValue> optionalValue,
Action<TValue> existAction)
{
Process(optionalValue, existAction, () => { });
}
public static IOptionalValue<TTarget> Select<TValue, TTarget>(
this IOptionalValue<TValue> optionalValue,
Func<TValue, TTarget> func)
{
return optionalValue.ProcessValue(func);
}
public static IOptionalValue<TTarget> SelectMany<TValue, TTarget>(
this IOptionalValue<TValue> optionalValue,
Func<TValue, IOptionalValue<TTarget>> func)
{
return optionalValue.ProcessValue(func);
}
public static IOptionalValue<T2> SelectMany<TValue, T1, T2>(
this IOptionalValue<TValue> optionalValue,
Func<TValue, IOptionalValue<T1>> func1,
Func<TValue, T1, T2> func2)
{
return optionalValue.SelectMany(
value => func1(value).Select(
value1 => func2(value, value1)
)
);
}
public static bool HasValue<TValue>(
this IOptionalValue<TValue> optionalValue)
{
return optionalValue.Process(delegate { return true; }, () => false);
}
public static TValue GetValue<TValue>(
this IOptionalValue<TValue> optionalValue)
{
return optionalValue.Process(
value => value,
() =>
{
throw new InvalidOperationException(
string.Format("Optional value of '{0}' type has no value.", typeof (TValue)));
}
);
}
public static TValue GetValueOrDefault<TValue>(
this IOptionalValue<TValue> optionalValue)
{
return optionalValue.Process(value => value, () => default(TValue));
}
public static IOptionalValue<TValue> ToOptionalValue<TValue>(
this TValue value) where TValue : class
{
return value == null ? Nothing<TValue>() : value.AsOptionalValue();
}
private class NotExistOptionalValue<TValue> : IOptionalValue<TValue>
{
public static readonly IOptionalValue<TValue> Instance = new NotExistOptionalValue<TValue>();
private NotExistOptionalValue()
{
}
public TResult Process<TResult>(
Func<TValue, TResult> existFunc, Func<TResult> notExistFunc)
{
return notExistFunc();
}
}
private class ExistOptionalValue<TValue> : IOptionalValue<TValue>
{
private readonly TValue value;
public ExistOptionalValue(TValue value)
{
this.value = value;
}
public TResult Process<TResult>(
Func<TValue, TResult> existFunc, Func<TResult> notExistFunc)
{
return existFunc(value);
}
}
}