在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中不起作用.
c# nullable nullreferenceexception null-conditional-operator
我有一个非常简单的例子:
class Program
{
class A
{
public bool B;
}
static void Main()
{
System.Collections.ArrayList list = null;
if (list?.Count > 0)
{
System.Console.WriteLine("Contains elements");
}
A a = null;
if (a?.B)
{
System.Console.WriteLine("Is initialized");
}
}
}
Run Code Online (Sandbox Code Playgroud)
行if (list?.Count > 0)编译完美,这意味着如果list是null,表达式Count > 0变为false默认.
但是,该行if (a?.B)抛出编译器错误,表示我无法隐式转换bool?为bool.
为什么一个人与另一个人不同?
您可能知道,DateTime?没有参数化ToString(为了格式化输出),并执行类似的操作
DateTime? dt = DateTime.Now;
string x;
if(dt != null)
x = dt.ToString("dd/MM/yyyy");
Run Code Online (Sandbox Code Playgroud)
会扔
方法'ToString'没有重载需要1个参数
但是,由于C#6.0和Elvis(?.)运算符,上面的代码可以替换为
x = dt?.ToString("dd/MM/yyyy");
Run Code Online (Sandbox Code Playgroud)
哪....有效!为什么?
我有几个页面,每个页面都有一个名为的属性Data.在另一个页面上,我将这样的数据设置为:
if (MyPage1 != null)
MyPage1.Data = this.data;
if (MyPage2 != null)
MyPage2.Data = this.data;
if (MyPage3 != null)
MyPage3.Data = this.data;
Run Code Online (Sandbox Code Playgroud)
是否有可能使用空条件运算符MyPage?我在考虑这样的事情:
MyPage?.Data = this.data;
Run Code Online (Sandbox Code Playgroud)
但是当我这样写时,我收到以下错误:
赋值的左侧必须是变量,属性或索引器.
我知道这是因为MyPage可能是null而左侧不再是变量.
这并不是说像我有它已经,但我只是想知道是否有任何可能使用空条件操作这个我不能使用它.
提前道歉:这个问题来自一个试图学习高级C#的硬核,未经过改造的C++开发人员.考虑以下:
if (myUserDefinedObject != null)
{
myUserDefinedObject.ToString();
}
Run Code Online (Sandbox Code Playgroud)
这显然不是线程安全的.另一方面,我看过两个教程说?(例如,Null条件运算符或'Elvis运算符')
myUserDefinedObject?.ToString();
Run Code Online (Sandbox Code Playgroud)
IS线程安全.除非编译器将[mutex?]锁定在它下面(颤抖),否则我不明白这是怎么回事.如果这个成语是线程安全的,有人可以指点我如何完成它的技术描述?如果它不是线程安全的,那么有没有人有一个实际上说它不是的参考?
我有这些扩展方法和枚举类型:
public static bool IsOneOf<T>(this T thing, params T[] things)
{
return things.Contains(thing);
}
public static bool IsOneOf<T>(this T? thing, params T[] things) where T : struct
{
return thing.HasValue && things.Contains(thing.Value);
}
public enum Color { Red, Green, Blue }
Run Code Online (Sandbox Code Playgroud)
if下面的第一个编译; 第二个不是:
if ((x.Y?.Color).IsOneOf(Color.Red, Color.Green))
;
if (x.Y?.Color.IsOneOf(Color.Red, Color.Green))
;
Run Code Online (Sandbox Code Playgroud)
它们仅因额外的括号而异.为什么我要这样做?
起初我怀疑它是从做一个双隐式转换bool?到bool,然后回bool?,但是当我删除第一个扩展方法,它抱怨不存在隐式转换,从bool到bool?.然后我检查了IL并且没有演员阵容.反编译回C#会产生如下情况:
if (!(y != null ? new Color?(y.Color) : new Color?()).IsOneOf<Color>(new Color[2]
{
Color.Red,
Color.Green
}));
Run Code Online (Sandbox Code Playgroud)
这对于我正在运行的CLR版本以及我的期望是好的.我没想到的是 …
我一直在关注C#6中添加的安全导航操作员功能.我一直期待它.但我发现了一些与我预期不同的行为.我意识到我真的不明白它是如何运作的.
鉴于这门课程
class Foo {
public int? Measure;
}
Run Code Online (Sandbox Code Playgroud)
这是使用new运算符的一些代码.
Foo f = new Foo { Measure = 3 };
Console.WriteLine(f?.Measure); // 3
f = new Foo { Measure = null };
Console.WriteLine(f?.Measure); // null
f = null;
Console.WriteLine(f?.Measure); // null
Run Code Online (Sandbox Code Playgroud)
到目前为止,一切都按预期工作. ?.当左侧不为null时访问成员,否则返回null.但是这里的事情朝着一个我没想到的方向发展.
var i = f?.Measure; // i is Nullable<int>
Console.WriteLine(i.HasValue); // false
Console.WriteLine(f?.Measure.HasValue); // null
Run Code Online (Sandbox Code Playgroud)
什么?
为什么我可以HasValue从中获得i,但不能从我指定的相同表达式中获取i?怎么可能HasValue是null?
编辑:我真正的问题是关于程序行为,而不是编译错误.我删除了有关编译的额外内容,并更加狭隘地将这个问题集中在为什么两个不同的结果被看似相同的逻辑返回.
我一直在玩C#6的Null Conditional Operator(这里有更多信息).
我非常喜欢语法,我认为它使代码更具可读性,但我认为当你遇到一个本身可能为null的对象上的属性值时,代码究竟要做什么是值得怀疑的.
例如,如果我有一个带有十进制属性的类,并且我想要对该十进制值进行条件检查,我会写如下:
if (foo?.Bar > max)
{
// do something
}
Run Code Online (Sandbox Code Playgroud)
从表面上看,这看起来很棒......如果foo不为null,则获取Bar的值并检查它是否大于最大值,如果是,则执行某些操作.
但是,如果foo为null会怎么样?!
如果实际上对象的值为null,则null条件运算符将返回null.它将对Bar的调用短路,并立即返回null,避免编程错误,否则会导致NullReferenceException.
我在这里写了一个小提琴,表明它确实起作用,正在做我期待它做的事情但是我无法理解它是如何决定条件的结果.
短路如何等于假?在我的脑海中,这段代码现在要说"如果foo为null,检查null是否> max,这是不可能的,所以返回false"或"如果foo为null,那么foo!= null将返回false,所以你得到一个假"但文档说null条件检查返回null,而不是false.
我在C#中使用新的空条件运算符时遇到了一个有趣的System.NullReferenceException.如果"MyObject"为null,则以下代码为我提供NullReferenceException:
await this.MyObject?.MyMethod()
Run Code Online (Sandbox Code Playgroud)
我希望如果"MyObject"为空,或者我误解了空条件运算符的用途,就不会调用"MyMethod"?
老路
int? myFavoriteNumber = 42;
int total = 0;
if (myfavoriteNumber.HasValue)
total += myFavoriteNumber.Value *2;
Run Code Online (Sandbox Code Playgroud)
新方法?
int? myFavoriteNumber = 42;
total += myFavoriteNumber?.Value *2; //fails
Run Code Online (Sandbox Code Playgroud) c# nullable null-propagation-operator null-conditional-operator