有没有办法只在分配的值不是 None 时才进行分配,否则什么都不做?
我们当然可以这样做:
x = get_value() if get_value() is not None
Run Code Online (Sandbox Code Playgroud)
但这将读取该值两次。我们可以将它缓存到一个局部变量中:
v = get_value()
x = v if v is not None
Run Code Online (Sandbox Code Playgroud)
但现在我们为一件简单的事情做了两个陈述。
我们可以写一个函数:
def return_if_not_none(v, default):
if v is not None:
return v
else:
return default
Run Code Online (Sandbox Code Playgroud)
然后做x = return_if_not_none(get_value(), x)。但是肯定已经有一个 Python 习惯用法可以实现这一点,无需访问x或get_value()两次,也无需创建变量?
换句话说,假设=??是一个类似于C# null 合并运算符的 Python 运算符。与 C# 不同??=,我们虚构的运算符检查右侧是否为None:
x = 1
y = 2
z = None
x =?? y …Run Code Online (Sandbox Code Playgroud) PHP 8.0 引入了 nullsafe 运算符,可以像这样使用$foo?->bar?->baz;。Undefined property: stdClass::$first_name我有一个在 php 8.1 上运行的代码示例,即使它使用 nullsafe 运算符,也会引发错误:
$reference = (object) $reference; // Cast of array to object
return [
'FirstName' => $reference?->first_name,
];
Run Code Online (Sandbox Code Playgroud)
为了解决该错误,我必须使用空合并运算符:
$reference = (object) $reference; // Cast of array to object
return [
'FirstName' => $reference->first_name ?? null,
];
Run Code Online (Sandbox Code Playgroud)
为什么 nullsafe 运算符在这种情况下会抛出错误?
我正在编写一个C#例程来调用存储过程.在我传入的参数列表中,其中一个值可能合法地为空.所以我以为我会使用这样的一行:
cmd.Parameters.Add(new SqlParameter("@theParam", theParam ?? DBNull.Value));
Run Code Online (Sandbox Code Playgroud)
不幸的是,这会返回以下错误:
CS0019:运营商'??' 不能应用于'string'和'System.DBNull'类型的操作数
现在,这似乎已经足够清楚,但我不明白其背后的基本原理.为什么这不起作用?(通常情况下,当我不明白为什么某些东西不能正常工作时,并不是它无法正常工作......而是我做错了.)
我是否真的需要将其延伸到更长的if-then声明中?
编辑:(顺便说一句,对那些建议只使用"null"的人,它不起作用.我原来认为null也会自动翻译成DBNull,但它显然没有.(谁知道?))
你认为C#会支持像?? = operator这样的东西吗?
而不是这个:
if (list == null)
list = new List<int>();
Run Code Online (Sandbox Code Playgroud)
有可能写:
list ??= new List<int>();
Run Code Online (Sandbox Code Playgroud)
现在,我可以使用(但在我看来,它不太可读):
list = list ?? new List<int>();
Run Code Online (Sandbox Code Playgroud) 有谁知道为什么最后一个不起作用?
object nullObj = null;
short works1 = (short) (nullObj ?? (short) 0);
short works2 = (short) (nullObj ?? default(short));
short works3 = 0;
short wontWork = (short) (nullObj ?? 0); //Throws: Specified cast is not valid
Run Code Online (Sandbox Code Playgroud) 我有两种相同功能的方法 - 一种是"if"条件,另一种是"??" 和铸造".哪种方法更好?为什么?
码:
Int16? reportID2 = null;
//Other code
//Approach 1
if (reportID2 == null)
{
command.Parameters.AddWithValue("@report_type_code", DBNull.Value);
}
else
{
command.Parameters.AddWithValue("@report_type_code", reportID2);
}
//Approach 2
command.Parameters.AddWithValue("@report_type_code", ((object) reportID2) ?? DBNull.Value);
Run Code Online (Sandbox Code Playgroud)
UPDATE
根据答案,以下是的好处 ??
注意:作为对象的铸造成本可以忽略不计.
参考
我知道这样做(myValue ?? new SomeClass())很像(myValue == null ? new SomeClass() : myValue)
但出于好奇,当我调用一个函数时,是否有任何性能优势
(getResult() ?? new SomeClass()).会getResult()被执行两次吗?这似乎不直观,因为我只指定了一次方法调用.
我有一个自定义WebControl,它实现了一个.Value返回Nullable <decimal> 的getter/setter
它是一个客户端过滤的文本框(TextBox包含javascript 的子类和用于设置/获取值的一些服务器端逻辑)
这是来自该控件的getter和setter:
public decimal? Value
{
get
{
decimal amount = 0;
if (!decimal.TryParse(this.Text, NumberStyles.Currency, null, out amount))
{
return null;
}
else
{
return amount;
}
}
set
{
if (!value.HasValue)
{
this.Text = "";
}
else
{
this.Text = string.Format("${0:#,##0.00}", value);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我看到的问题是这个语句的输出:
decimal Amount = uxAmount.Value ?? 0M;
Run Code Online (Sandbox Code Playgroud)
当uxAmount.Value返回10000 时,我看到Amount被设置为"0" .
这符合我的预期(原则是套管的变化):
decimal? _Amount = uxAmount.Value;
decimal amount = _Amount ?? 0;
Run Code Online (Sandbox Code Playgroud)
我也看到了这种行为(最近)在调用Linq2Sql数据上下文中定义的UDF函数以及空合并运算符时,我知道我的UDF调用返回了预期值,但我得到的是RHS值. …
假设我有这个:
$username = (string) $inputs['username'] ?? null;
Run Code Online (Sandbox Code Playgroud)
如果$inputs['username']设置了,那么我希望它转换为string. 如果没有设置,那么$username应该是null。
但是,目前如果$inputs['username']未设置,它将是一个空字符串而不是 null。
我怎样才能解决这个问题?或者这是故意的行为?
Q1:我认为??在以下情况下将不会执行任何操作:
$a = [1, 2];
foreach ($a ?? [] as &$v) {
$v++;
}
var_dump($a);
Run Code Online (Sandbox Code Playgroud)
但为什么?
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
Run Code Online (Sandbox Code Playgroud)
Q2:这更奇怪:
foreach ($a = [1, 2] as &$v) {
$v++;
}
var_dump($a);
// output
array(2) {
[0]=>
int(1)
[1]=>
int(2)
}
Run Code Online (Sandbox Code Playgroud)
我的想法:我认为表达式不可引用,但foreach捕获错误或以某种方式然后复制。有效的参考资料:
$a = 1;
$c = &$a;
Run Code Online (Sandbox Code Playgroud)
不工作:
$a = 1;
$c = &($a);
$c = &($a ?? []);
$c = &($a + 1);
Run Code Online (Sandbox Code Playgroud)
??复印吗?我只是不想用 if 为 null 来包装foreach, …