我不太确定如何说出这个问题,但情况如下:
说我有以下课程:
public class SampleClass
{
public int Number { get; set; }
}
我知道你可以null合并包含的类:
SampleClass newSampleClass = possibleNullSampleClass ?? notNullSampleClass;
有没有办法在属性上执行某种null合并,所以我不必这样做:
int? num = sampleClass != null ? new int?(sampleClass.Number) : 5;
看起来像???
运算符之类的东西执行此检查非常有用,所以我可以这样做:
int? num = sampleClass.Number ??? 5;
在C#中是否可以这样?
答案 0 :(得分:5)
目前没有这样的运营商。但在C#6中,“安全导航”操作符将出现,您将能够编写
int number = sampleClass?.Number;
即使sampleClass
等于null
,此代码也不会因NullRef而失败。现在,您可以使用以下扩展方法从对象中提取值并封装null-check:
public static TResult Maybe<TSource, TResult>(
this TSource source, Func<TSource, TResult> produceResult, Func<TResult> produceDefault)
where TSource : class
{
return source == null ? produceDefault() : produceResult(source);
}
并按如下方式使用:
int numberOrFive = sampleClass.Maybe(c => c.Number, () => 5);
答案 1 :(得分:3)
没有现有的运营商可以做到这一点。您已经展示了一种完全可以接受的处理问题的方法。
如果你愿意,你可以将逻辑包装在一个方法中,但我不确定这是否真的值得付出努力:
public static TResult Access<TSource, TResult>(
TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
where TSource : class
{
if (obj == null)
return defaultIfNull;
else
return selector(obj);
}
SampleClass sampleClass = null;
int num = Access(sampleClass, s => s.Number, 5);
(如果你愿意,你可以考虑将其作为一种扩展方法,尽管我个人对所有类的扩展方法都很谨慎。还要考虑其他名称,例如Use
。)
答案 2 :(得分:0)
我打算提议修改Servy的帖子。我认为如果它可以处理一般情况,他的方法将证明是有用的,其中在对象链的任何地方都可以存在null。
public static TResult Access<TSource, TResult>(
TSource obj, Func<TSource, TResult> selector, TResult defaultIfNull)
where TSource : class
{
TResult result;
try
{
result = selector(obj);
}
catch ( NullReferenceException)
{
result = defaultIfNull;
}
return result;
}
这样,如果您尝试访问 ZipCode = Customer.Address.ZipCode;
如果客户或地址为空,则受到保护
答案 3 :(得分:0)
你不能在C#中做到这一点。您需要明确地测试无效性:
MyWidget x ;
int? v = x == null ? (int?)x.SomeProperty : (int?) null ;
如果您认为它有用,可以在Microsoft Connect上记录您的建议:
http://connect.microsoft.com/VisualStudio
我愿意成为他们的想法,并认为构建语言不够有用。
答案 4 :(得分:0)
你完全可以这样做:
var x = (myObject ?? DefaultObject).Field;
这就是......
var x = (myObject == null) ? myObject.Field : defaultValue;