注意:这个问题是在引进之前要求的.?在C#6/Visual Studio的2015年运营商.
我们都去过那里,我们有像cake.frosting.berries.loader这样的深层属性,我们需要检查它是否为空,所以没有例外.要做的是使用短路if语句
if (cake != null && cake.frosting != null && cake.frosting.berries != null) ...
Run Code Online (Sandbox Code Playgroud)
这不是很优雅,也许应该有一种更简单的方法来检查整个链,看看它是否出现了null变量/属性.
是否可以使用某种扩展方法或者它是一种语言功能,还是只是一个坏主意?
这里的基本问题 - 我有许多代码行,如下所示:
var a = (long_expression == null) ? null : long_expression.Method();
Run Code Online (Sandbox Code Playgroud)
类似的行在这个函数中重复了很多.long_expression每次都不一样.我试图找到一种方法来避免重复long_expression,但保持这种紧凑.像是相反的东西operator ??.目前我正在考虑放弃并将其放在多行上,如:
var temp = long_expression;
var a = (temp == null) ? null : temp.Method();
Run Code Online (Sandbox Code Playgroud)
但我很好奇是否有一些我不知道的聪明语法会使这更加简洁.
继续我在C#中表达F#想法的调查,我想要一个管道前进算子.对于包含在IEnumerable中的任何东西,我们已经拥有它,因为你可以.NextFunc()到你心中的内容.但是,例如,如果最后有任何类似折叠的缩减,则无法将其结果输入函数.
这里有两种扩展方法,我想知道是否有其他人试过这个,如果这是个好主意(编辑:现在有了Earwicker的可能包括在内):
public static void Pipe<T>(this T val, Action<T> action) where T : class
{ if (val!=null) action(val); }
public static R Pipe<T, R>(this T val, Func<T, R> func) where T : class where R : class
{ return val!=null?func(val):null; }
Run Code Online (Sandbox Code Playgroud)
然后你可以写下这样的东西:
Func<string, string[]> readlines = (f) => File.ReadAllLines(f);
Action<string, string> writefile = (f, s) => File.WriteAllText(f, s);
Action<string, string> RemoveLinesContaining = (file, text) =>
{
file.Pipe(readlines)
.Filter(s => !s.Contains(text))
.Fold((val, sb) => sb.AppendLine(val), …Run Code Online (Sandbox Code Playgroud) 如何在深层lamda表达式中检查空值?
比方说,我有一个嵌套了几层深度的类结构,我想执行以下lambda:
x => x.Two.Three.Four.Foo
Run Code Online (Sandbox Code Playgroud)
如果Two,Three或Four为null,我希望它返回null,而不是抛出System.NullReferenceException.
public class Tests
{
// This test will succeed
[Fact]
public void ReturnsValueWhenClass2NotNull()
{
var one = new One();
one.Two = new Two();
one.Two.Three = new Three();
one.Two.Three.Four = new Four();
one.Two.Three.Four.Foo = "blah";
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal("blah", result);
}
// This test will fail
[Fact]
public void ReturnsNullWhenClass2IsNull()
{
var one = new One();
var result = GetValue(one, x => x.Two.Three.Four.Foo);
Assert.Equal(null, result);
}
private TResult GetValue<TModel, TResult>(TModel model, …Run Code Online (Sandbox Code Playgroud) 可能重复:
"如果object为null,则返回null;如果object不为null,则返回object.member"
有些语言有一个安全的导航操作符,让您不必担心空引用异常.
Groovy语言示例:
String lname = person.Name.ToLowerCase(); //throws exception if Name is null
String lname = person.Name?.ToLowerCase();//lname will be null if Name was null
Run Code Online (Sandbox Code Playgroud)
如何在C#中完成与此类似的操作?到目前为止,我的解决方案是这样的扩展方法:
public static T o<T>(this T obj) where T : new()
{
return obj != null ? obj : new T();
}
//used like: String lname = person.o().Name; //returns null if person was null
Run Code Online (Sandbox Code Playgroud)
但是,这仅适用于某些情况.
可能重复:
C#中的安全导航操作员?
"如果object为null,则为null;如果object为null,则为object.member"的快捷方式
在我的XML处理项目中,我必须浏览链式属性以获得所需的值.例如,obj1.obj2.obj3.obj4.obj....Value.并且可能退出此链中的任何对象为null.
我用Google搜索了"c#中的NullSafe导航"并找到了一些不错的文章.从Post之一,我有了实现自定义扩展的想法.现在我对这个扩展的性能有疑问.我有这3个解决方案.任何人都可以建议我采用哪一种(在性能方面)?
选项1(使用本文中解释的逻辑):
//custom extension method
public static TOutput IfNotNull<TInput, TOutput>(this TInput x, Func<TInput, TOutput> f)
where TInput : class
where TOutput : class
{
return x == null ? null : f(x);
}
//with custom extension method -- Very neat & clean.. but what about performance?
string x = obj1
.IfNotNull(x => x.obj2)
.IfNotNull(x => x.obj3)
.IfNotNull(x => x.obj4)
.IfNotNull(x => x.obj5)
.IfNotNull(x => x.Value);
Run Code Online (Sandbox Code Playgroud)选项2:
//with NullCheck -- probably …Run Code Online (Sandbox Code Playgroud)因此,有一个合并运算符??,允许方便地处理空对象(IE. MyDisplayString = MyString ?? "n/a";)
但是有一个很好的花哨的操作符来处理对象属性的类似情况吗?例如,假设您感兴趣的属性是属性的属性,例如:MyDataObject.MySubModel.MyProperty
如果MyProperty为null,则需要合并为"n/a".你可以??在这里使用,但如果MyDataObject是null或MyDataObject.MySubModel?
在尝试获取元素的可选属性和元素时,这也会出现XML.IE:MyString = MyElement.Attribute("MyOptionalAttribute").Value ?? "n/a"; 如果属性不存在则失败.
处理这种情况有一种很好的方式吗?