首页 新闻 会员 周边 捐助

请教C# 6.0的Null条件运算符写法

0
悬赏园豆:30 [待解决问题]

目前在C#中的写法是这样的:

var refreshToken = await Get(id);
if (refreshToken != null)
{
    refreshToken.IsActive = false;
}

想使用C# 6.0的Null条件运算符改写,请问该如何写?

C#
问题补充:

想达到类似这样的效果:

目前有2个折衷的解决方法:

1)不优雅的解决方法

((await Get(id)) ?? new RefreshToken()).IsActive = false;

2)丑陋的解决方法

给RefreshToken类增加一个SetIsActive方法:

public bool IsActive { get; set; }
public void SetIsActive(bool value)
{
    IsActive = value;
}

然后使用Null条件运算符时调用这个方法:

(await Get(id))?.SetIsActive(false);
dudu的主页 dudu | 高人七级 | 园豆:30778
提问于:2015-07-22 16:02
< >
分享
所有回答(4)
0

按照它的规则,应该是:refreshToken?.IsActive = false; 还没安装4.6,没法测试。

幻天芒 | 园豆:37207 (高人七级) | 2015-07-22 16:07

这样写不行,见下图:

支持(1) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-22 16:19

@dudu: 那看来是设定问题了~~

支持(0) 反对(0) 幻天芒 | 园豆:37207 (高人七级) | 2015-07-23 09:40
1
refreshToken?.IsActive = false;//no
var isActive = refreshToken?.IsActive;//yes

?判断是否为null,应该只能get,而不能set。

田园里的蟋蟀 | 园豆:423 (菜鸟二级) | 2015-07-22 17:19

我好奇的是为什么set就不可以。

Null条件运算符是支持方法调用的。

如果给RefreshToken加一个SetIsActive()方法就可以:

(await Get(id))?.SetIsActive(false);

而IsActive属性在编译时,实际也是被转换为get_IsActive与set_IsActive方法。如果这个set_IsActive方法可以被调用,就可以进行set。或者编译器将?.IsActive=false;翻译为set_IsActive方法调用。

支持(0) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-22 17:56

@田园里的蟋蟀: 第1个链接错了地址

支持(0) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-22 18:50

@dudu: 已修改。

支持(0) 反对(0) 田园里的蟋蟀 | 园豆:423 (菜鸟二级) | 2015-07-22 19:27
1

私以为:
refreshToken?.IsActive = false;其IsActive属性是一直可以get、set的。
而目前编译器只实现了Get操作,还没支持Set,所以推断不出art不为空就赋值给prop1、为空就不
赋值的行为。

加一个SetIsActive()这个可以,是因为?.已经明确了refreshToken不为空才调方法,所以方法内赋值是理所当然的。


或许7.0就有了。

蘑菇先生 | 园豆:224 (菜鸟二级) | 2015-07-23 10:46
0

这个设定应该是有问题的,因为refreshToken?.IsActive返回的实际上是一个bool拷贝值,估计代码检测是这样理解的:

 

而这个返回的bool值是不能被赋值的。实际上,从“Null条件运算符”的字面意义来看,它是一个运算符,结果是一个右值且是值类型,这个结果当然不能赋值了。

如果IsActive换成引用类型的值,这种写法是没问题的:

以吾之名 | 园豆:204 (菜鸟二级) | 2015-07-23 16:26

我实际想进行的操作是 refreshToken?(.IsActive = false) ,是希望编译器将 .IsActive = false 翻译为对set_IsActive(false)方法的调用。

支持(0) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-23 16:38

@dudu: 比如(a==b)=false,这样肯定语法错误,这个运算符就是提供一个返回值,能执行什么操作时返回值决定的

支持(0) 反对(0) 以吾之名 | 园豆:204 (菜鸟二级) | 2015-07-23 16:44

@以吾之名: 那为什么调用方法就可以呢?

refreshToken?.SetIsActive(false);

 

支持(0) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-23 16:50

@dudu: 

https://roslyn.codeplex.com/discussions/540281

请参考上面这篇文章,里面提到:

Semantics

The semantics are like applying the ternary operator to a null equality check, a null literal and a non-question-marked application of the operator, except that the expression is evaluated only once:

e?.m(…) => ((e == null) ? null : e0.m(…))
e?.x => ((e == null) ? null : e0.x)
e?.$x => ((e == null) ? null : e0.$x)
e?[…] => ((e == null) ? null : e0[…])

Where e0 is the same as e, except if e is of a nullable value type, in which case e0 is e.Value

所以实际上,代码等同如下:

refreshToken?.IsActive=false => (int?)((refreshToken==null)?null:refreshToken.IsActive)=false

refreshToken?.SetIsActive(false) => ((refreshToken==null)?null:refreshToken.SetIsActive(false))

支持(0) 反对(0) 以吾之名 | 园豆:204 (菜鸟二级) | 2015-07-23 18:02

@dudu: 这个操作符应该类似“.”成员操作符,但是和成员操作符是有区别的,正常的成员操作符能直接处理属性赋值,但是这个操作符不行

支持(0) 反对(0) 以吾之名 | 园豆:204 (菜鸟二级) | 2015-07-23 18:05

@以吾之名: 是的,就是Roslyn解析的问题,如果Roslyn能改进一下,应该可以解决这个问题。

支持(0) 反对(0) dudu | 园豆:30778 (高人七级) | 2015-07-23 18:10
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册