唯一的方式使用空结合运营商
-
07-07-2019 - |
题
我知道标准的方式使用空结合运营商在C#是设定缺省值。
string nobody = null;
string somebody = "Bob Saget";
string anybody = "";
anybody = nobody ?? "Mr. T"; // returns Mr. T
anybody = somebody ?? "Mr. T"; // returns "Bob Saget"
但还有什么可以 ??
可以使用?它似乎没有用的,因为这三元的操作者,除了从更加简明和更容易阅读于:
nobody = null;
anybody = nobody == null ? "Bob Saget" : nobody; // returns Bob Saget
所以给予较少甚至不知道有关空凝聚操作人员...
你有没有用
??
对别的东西吗?是
??
有必要,或者你应该仅仅使用三操作者(这 最熟悉)
解决方案
好吧,首先,它是更容易链于标准的三元:
string anybody = parm1 ?? localDefault ?? globalDefault;
与
string anyboby = (parm1 != null) ? parm1
: ((localDefault != null) ? localDefault
: globalDefault);
它也运作良好,如果null-可能对象不是一个变量:
string anybody = Parameters["Name"]
?? Settings["Name"]
?? GlobalSetting["Name"];
与
string anybody = (Parameters["Name"] != null ? Parameters["Name"]
: (Settings["Name"] != null) ? Settings["Name"]
: GlobalSetting["Name"];
其他提示
我已经用它作为一个懒惰的负载一个班轮:
public MyClass LazyProp
{
get { return lazyField ?? (lazyField = new MyClass()); }
}
读?自己决定。
我已经找到了有用的,在两个"有点奇怪"的方式:
- 作为一个替代的用于具有一个
out
参数的时候写的TryParse
例程(即返回的零价值,如果分析失败) - 作为一个"不知道"的表示对于比较
后者需要一点更多的信息。通常当你建立一个比较有多种元素,你需要看是否第一部分的比较(例如年龄)给出了一个明确的答案,那么下一个部分(例如名)只有在第一部分没有帮助。使用空结合运营商意味着你可以写很简单的比较(无论是为排序或平等).例如,使用几个帮手类 MiscUtil:
public int Compare(Person p1, Person p2)
{
return PartialComparer.Compare(p1.Age, p2.Age)
?? PartialComparer.Compare(p1.Name, p2.Name)
?? PartialComparer.Compare(p1.Salary, p2.Salary)
?? 0;
}
诚然,我现在有ProjectionComparer在MiscUtil,随着一些扩展,其作出这种事甚至更加容易,但它仍然是整洁。
同样可以做为检查对于参考平等的(或无效)时开始执行平等的。
另一个优点是,三元的操作者需要一双重评价或暂时的变量。
考虑这一点,例如:
string result = MyMethod() ?? "default value";
同时,用三操作者你留下:
string result = (MyMethod () != null ? MyMethod () : "default value");
它呼吁MyMethod两次,或者:
string methodResult = MyMethod ();
string result = (methodResult != null ? methodResult : "default value");
无论哪种方式,空结合运营商是清洁的,我猜测,更有效率。
另一个要考虑的是,合并操作者不要叫获得方法的一个酒店的两倍,三元做。
所以在有些情况下,您不应该使用三,例如:
public class A
{
var count = 0;
private int? _prop = null;
public int? Prop
{
get
{
++count;
return _prop
}
set
{
_prop = value;
}
}
}
如果你使用:
var a = new A();
var b = a.Prop == null ? 0 : a.Prop;
吸气将被称为两次 count
变量将等于2,如果你使用:
var b = a.Prop ?? 0
的 count
变量将等于1,因为这是应该的。
最大的优点,我找到的 ??
算是,你可以容易地转换为可空值类型非空类型:
int? test = null;
var result = test ?? 0; // result is int, not int?
我经常使用这个在皇宫查询:
Dictionary<int, int?> PurchaseQuantities;
// PurchaseQuantities populated via ASP .NET MVC form.
var totalPurchased = PurchaseQuantities.Sum(kvp => kvp.Value ?? 0);
// totalPurchased is int, not int?
我已经使用??在我的执行情况的IDataErrorInfo:
public string Error
{
get
{
return this["Name"] ?? this["Address"] ?? this["Phone"];
}
}
public string this[string columnName]
{
get { ... }
}
如果任何个人的财产是在一个"错误"状态,我得到这一错误,否则我得到空。确实很好。
你可以使用空结合运营商,以使它更清洁的处理情况的一个可选择的参数并不是设置:
public void Method(Arg arg = null)
{
arg = arg ?? Arg.Default;
...
我喜欢使用空结合运营商懒载的某些属性。
一个非常简单的(和人为的)示例只是为了说明我的观点:
public class StackOverflow
{
private IEnumerable<string> _definitions;
public IEnumerable<string> Definitions
{
get
{
return _definitions ?? (
_definitions = new List<string>
{
"definition 1",
"definition 2",
"definition 3"
}
);
}
}
}
是什么??有必要,或者你应该仅仅使用三操作者(大多数熟悉)
实际上,我的经验是,所有太少的人都熟悉的三元的运营商(或者更正确, 有条件的 操作者; ?:
是"三元"在同样的意义, ||
或是二进制的 +
是无论是一元或二元;但是它会发生是唯一的三操作人员在多种语言),因此至少在有限的样品,你的发言失败的权利。
此外,如前所述,有一个主要的情况时空结合运营商是非常有用的,这就是每当的表达,以评估具有任何副作用。在这种情况下,您 不能 使用条件的操作员没有任何(a)介绍临时变量,或(b)不断变化的实际逻辑的应用程序。(b)显然是不适当的,在任何情况下,虽然它是个人的偏好,我不喜欢凌乱的宣言》的范围有很多多余的,即使短暂的变量,因此,(a)为了在这一特定情况。
当然,如果你需要做个检查的结果,有条件的操作员,或一组 if
区块,很可能工具的工作。但简单"如果这是null,使用,否则使用",空结合运营商 ??
是完美的。
唯一的问题是空结合运营者没有检测到的空串。
即
string result1 = string.empty ?? "dead code!";
string result2 = null ?? "coalesced!";
输出:
result1 = "" result2 = coalesced!
目前,我正在看到压倒一切的??操作员的工作围绕这一点。它肯定会很方便有这种内置的框架。
想法?
有一件事我已经做了很多最近被使用空凝聚为备份 as
.例如:
object boxed = 4;
int i = (boxed as int?) ?? 99;
Console.WriteLine(i); // Prints 4
它也有用于备份的长链 ?.
可能每个失败
int result = MyObj?.Prop?.Foo?.Val ?? 4;
string other = (MyObj?.Prop?.Foo?.Name as string)?.ToLower() ?? "not there";
是什么??有必要,或者你应该仅仅使用三操作者(大多数熟悉)
你应该使用什么最好的表示你的意图。由于没 是 空结合运营商, 使用它.
另一方面,由于它是如此专业,我不认为它具有其他用途。我希望有一个适当的过载 ||
操作者,以其他语言做。这将是更简单的语言设计。但是嗯...
酷!算我一个人不知道有关空结合运营商--这是非常漂亮的东西。
我发现更容易阅读于三操作员。
首先想到在这里我可能会使用它是为了保持我的所有缺省参数在一个地方。
public void someMethod( object parm2, ArrayList parm3 )
{
someMethod( null, parm2, parm3 );
}
public void someMethod( string parm1, ArrayList parm3 )
{
someMethod( parm1, null, parm3 );
}
public void someMethod( string parm1, object parm2, )
{
someMethod( parm1, parm2, null );
}
public void someMethod( string parm1 )
{
someMethod( parm1, null, null );
}
public void someMethod( object parm2 )
{
someMethod( null, parm2, null );
}
public void someMethod( ArrayList parm3 )
{
someMethod( null, null, parm3 );
}
public void someMethod( string parm1, object parm2, ArrayList parm3 )
{
// Set your default parameters here rather than scattered through the above function overloads
parm1 = parm1 ?? "Default User Name";
parm2 = parm2 ?? GetCurrentUserObj();
parm3 = parm3 ?? DefaultCustomerList;
// Do the rest of the stuff here
}
位的一个奇怪的使用情况,但我有一个方法那里一个 IDisposable
对象可能是通过为阿根廷(并因此设置的父母),但也可能是null(和因此应该创建并设在本地的方法)
使用它,代码看起来像
Channel channel;
Authentication authentication;
if (entities == null)
{
using (entities = Entities.GetEntities())
{
channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
[...]
}
}
else
{
channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
[...]
}
但有一个空凝聚变更整洁
using (entities ?? Entities.GetEntities())
{
channel = entities.GetChannelById(googleShoppingChannelCredential.ChannelId);
[...]
}
空结合运营商
这种操作检查的变量,如果空,返回的价值下来的"??" 操作者还得到保存价值的变量。
例如:-1
var name=”ATHUL”;
var result =name ?? “The name is null”
Console.WriteLine(result);
o/p:ATHUL
例如:-2的
var name=null;
var result =name ?? “The name is null”
Console.WriteLine(result);
o/p:名字是空的