Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/eclipse/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#中的安全导航操作员?_C# - Fatal编程技术网

C#中的安全导航操作员?

C#中的安全导航操作员?,c#,C#,可能重复: 有些语言有一个安全的导航操作符,让您不用担心空引用异常 语言示例: 如何在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 pe

可能重复:

有些语言有一个安全的导航操作符,让您不用担心空引用异常

语言示例:

如何在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
publicstaticto(thistobj),其中T:new()
{
返回obj!=null?obj:new T();
}
//类似于:String lname=person.o().Name//如果person为null,则返回null

但是,这只在某些情况下有效。

我不知道如何从保证不为null的对象返回null,但是为了保证对象引用,可以使用
??

比如:

string lname = (person.Name??String.Empty).ToLower();
对于null大小写,它将返回一个空字符串而不是null,但它可以工作

返回空字符串比返回空字符串更有意义;如果返回null,如果将另一个运算符链接到它,它将再次抛出。

在今天的C语言中不存在,但您可以使用
SelectMany
编写它

String lname = from _ in person.Name from s in _.ToUpper() select s;


(这是Bart De Smet在中的建议。请参见幻灯片#6。)

对于这种情况,我倾向于使用名为
IfNotNull
的扩展方法:

public static OUT IfNotNull<IN, OUT>(this IN v, Func<IN, OUT> f) 
  where IN : class where OUT : class
{
  return v == null ? null : f(v);
}
public static OUT IfNotNull(这在v中,函数f中)
在哪:课堂在哪:课堂
{
返回v==null?null:f(v);
}
更复杂的是引入“可能”的概念。德里克·贝利(derick bailey)举了一个例子

更新:


到目前为止,有一个空传播运算符,它在语法上与Groovy运算符完全相同。

您正在寻找C语言版本6(在Visual Studio 2015中推出)中引入的短路

我的回答的其余部分是为C语言的早期版本编写的,这些版本没有
?。
操作符


一般来说,如果你正在访问一个深深的“嵌套”属性,比如<代码> OutTyMistObjist.A.B.C.x/Cuth>,你应该考虑重新设计你的代码,因为这样一个访问可能表明你违反了既定的OO原则(比如最少知识的原理,Law of Demeter)。

其他一些选择:

首先是一个反建议-不要这样做:

string lname = null;
try
{
    lname = Person.Name.ToLower();
}
catch (NullReferenceException ex) { }  // inefficient and ugly
Second,使用类似于
Maybe
单子的东西-您可以自己定义这样的类型。它基本上是一个
Nullable
,它实现了
IEnumerable
,当没有设置值时,它返回一个空序列;如果设置了值,则返回一个正好包含一个元素的序列。然后按如下方式使用它:

Maybe<string> personName = person.Name;
var lname = (from name in personName select name.ToLower()).FirstOrDefault();


p.S.,既然我们已经开始了检查
null
的主题,在访问其
名称
属性之前,不要忘记检查
person
是否为
null
。;-)

这似乎是一个很好的解决方案。允许您不中断方法链接,也不必引入临时变量,这是我希望使用安全导航运算符的主要原因。这取决于
OUT
是否为可空类型。您可以通过以下方式将其扩展到所有类型:1。删除
,其中OUT:class
,2。将主体更改为
returnv==null?违约(OUT):f(v)。v如何从o派生?这就是关键所在,如果o不为空,就可以用它做某事。你可以编写一个
ToLowerCase
扩展方法,但我可能只会在string对象上使用内置的
ToLower
方法。+1用于使用
操作符。??是我最喜欢的C#运算符。请注意,在本例中,
SelectMany
并不是常见的LINQ
SelectMany
,而是一个自定义的
SelectMany
,它是为实现
Maybe
单子而创建的。在编写本文时,这样一个功能实际上是为C#6设计的:请参阅
string lname = null;
try
{
    lname = Person.Name.ToLower();
}
catch (NullReferenceException ex) { }  // inefficient and ugly
Maybe<string> personName = person.Name;
var lname = (from name in personName select name.ToLower()).FirstOrDefault();
var lname = person.Name != null ? person.Name.ToLower() : null;