Jon*_*agh 87 c# nullable nullreferenceexception null-conditional-operator
在C#中,假设您希望在此示例中从PropertyC中提取值,而ObjectA,PropertyA和PropertyB都可以为null.
ObjectA.PropertyA.PropertyB.PropertyC
如何使用最少量的代码安全地获取PropertyC?
现在我会检查:
if(ObjectA != null && ObjectA.PropertyA !=null && ObjectA.PropertyA.PropertyB != null)
{
// safely pull off the value
int value = objectA.PropertyA.PropertyB.PropertyC;
}
Run Code Online (Sandbox Code Playgroud)
做更像这样的事情会很好(伪代码).
int value = ObjectA.PropertyA.PropertyB ? ObjectA.PropertyA.PropertyB : defaultVal;
Run Code Online (Sandbox Code Playgroud)
可能甚至进一步崩溃与空合并运算符.
编辑最初我说我的第二个例子就像js,但是我把它改成了psuedo-code,因为它被正确地指出它在js中不起作用.
Phi*_*gan 98
在C#6中,您可以使用Null条件运算符.所以最初的测试将是:
int? value = objectA?.PropertyA?.PropertyB?.PropertyC;
Run Code Online (Sandbox Code Playgroud)
Krz*_*nek 26
短扩展方法:
public static TResult IfNotNull<TInput, TResult>(this TInput o, Func<TInput, TResult> evaluator)
where TResult : class where TInput : class
{
if (o == null) return null;
return evaluator(o);
}
Run Code Online (Sandbox Code Playgroud)
运用
PropertyC value = ObjectA.IfNotNull(x => x.PropertyA).IfNotNull(x => x.PropertyB).IfNotNull(x => x.PropertyC);
Run Code Online (Sandbox Code Playgroud)
这个简单的扩展方法可以在http://devtalk.net/csharp/chained-null-checks-and-the-maybe-monad/上找到.
编辑:
在使用它之后我认为这个方法的正确名称应该是IfNotNull()而不是原始的With().
Sam*_*Sam 16
你能为你的班级添加一个方法吗?如果没有,您是否考虑过使用扩展方法?您可以为名为的对象类型创建扩展方法GetPropC().
例:
public static class MyExtensions
{
public static int GetPropC(this MyObjectType obj, int defaltValue)
{
if (obj != null && obj.PropertyA != null & obj.PropertyA.PropertyB != null)
return obj.PropertyA.PropertyB.PropertyC;
return defaltValue;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
int val = ObjectA.GetPropC(0); // will return PropC value, or 0 (defaltValue)
Run Code Online (Sandbox Code Playgroud)
顺便说一句,这假设您使用的是.NET 3或更高版本.
Tho*_*que 12
你这样做的方式是正确的.
您可以使用Linq表达式使用类似于此处描述的技巧:
int value = ObjectA.NullSafeEval(x => x.PropertyA.PropertyB.PropertyC, 0);
Run Code Online (Sandbox Code Playgroud)
但手动检查每个房产要慢得多......
Col*_*nic 10
更新2014:C#6有一个新的运算符,?.称为"安全导航"或"空传播"
parent?.child
Run Code Online (Sandbox Code Playgroud)
你显然正在寻找Nullable Monad:
string result = new A().PropertyB.PropertyC.Value;
Run Code Online (Sandbox Code Playgroud)
变
string result = from a in new A()
from b in a.PropertyB
from c in b.PropertyC
select c.Value;
Run Code Online (Sandbox Code Playgroud)
null如果任何可空属性为null,则返回; 否则,价值Value.
class A { public B PropertyB { get; set; } }
class B { public C PropertyC { get; set; } }
class C { public string Value { get; set; } }
Run Code Online (Sandbox Code Playgroud)
LINQ扩展方法:
public static class NullableExtensions
{
public static TResult SelectMany<TOuter, TInner, TResult>(
this TOuter source,
Func<TOuter, TInner> innerSelector,
Func<TOuter, TInner, TResult> resultSelector)
where TOuter : class
where TInner : class
where TResult : class
{
if (source == null) return null;
TInner inner = innerSelector(source);
if (inner == null) return null;
return resultSelector(source, inner);
}
}
Run Code Online (Sandbox Code Playgroud)
此代码是"代码量最少",但不是最佳实践:
try
{
return ObjectA.PropertyA.PropertyB.PropertyC;
}
catch(NullReferenceException)
{
return null;
}
Run Code Online (Sandbox Code Playgroud)
假设你有类型的空值,一种方法是:
var x = (((objectA ?? A.Empty).PropertyOfB ?? B.Empty).PropertyOfC ?? C.Empty).PropertyOfString;
Run Code Online (Sandbox Code Playgroud)
我是C#的忠实粉丝,但新Java(1.7?)中的一个非常好的东西是.?运营商:
var x = objectA.?PropertyOfB.?PropertyOfC.?PropertyOfString;
Run Code Online (Sandbox Code Playgroud)
我在新的 C# 6.0 中看到了一些东西,这是通过使用“?” 而不是检查
例如而不是使用
if (Person != null && Person.Contact!=null && Person.Contact.Address!= null && Person.Contact.Address.City != null)
{
var city = person.contact.address.city;
}
Run Code Online (Sandbox Code Playgroud)
你只需使用
var city = person?.contact?.address?.city;
Run Code Online (Sandbox Code Playgroud)
我希望它对某人有帮助。
更新:
你现在可以这样做
var city = (Person != null)?
((Person.Contact!=null)?
((Person.Contact.Address!= null)?
((Person.Contact.Address.City!=null)?
Person.Contact.Address.City : null )
:null)
:null)
: null;
Run Code Online (Sandbox Code Playgroud)