这个运算符是什么,“??”

What is this operator, "??"

我正在进行升级项目,最近开始遇到 DLL 升级版本的问题。我反编译了原来的dll,发现如下if语句:

if (fieldConfiguration == null && Context.ContentDatabase != null)
{
    Item obj = Context.ContentDatabase.SelectSingleItem(
        string.Format("//*[@@templateid='{0}' and @@key='{1}']", 
            (object) TemplateIDs.TemplateField, (object) fieldName));
}

然后我反编译了升级版的DLL,语句如下:

if (fieldConfiguration == null && (Context.ContentDatabase ?? Context.Database) != null)
{
    Item obj = Context.ContentDatabase.SelectSingleItem(
        string.Format("//*[@@templateid='{0}' and @@key='{1}']", 
            (object) TemplateIDs.TemplateField, (object) fieldName));
}

我能够通过使用 dotPeek 反编译 DLL 并使用 dotPeek 符号服务器功能逐步完成代码。我可以看到使用升级 DLL 时代码失败,因为 Context.ContentDatabase 为空。我不明白的是如何评估双三元运算符。有人可以为我澄清那里发生了什么吗?似乎这个程序集的创建者想要对 Context.ContentDatabase 进行空检查,但可能犯了一个错误。感谢您的帮助!

如果 Context.ContentDatabase 不为空,

(Context.ContentDatabase ?? Context.Database) 表达式最终结果为 Context.ContentDatabase,否则为 Context.Database。空合并运算符是向简洁 null 检查迈出的一步。

文档:https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-conditional-operator

嗯,是的,这看起来像一个错误。代码正在查找 Context.ContentDatabaseContext.Database 是否不是 null,然后继续使用前者,即使它是 null.

代码应如下所示:

var database = Context.ContentDatabase ?? Context.Database;

if (fieldConfiguration == null && database != null)
{
    Item obj = database.SelectSingleItem(
        string.Format("//*[@@templateid='{0}' and @@key='{1}']", 
            (object) TemplateIDs.TemplateField, (object) fieldName));
}

它使用空合并运算符将数据库存储在一个单独的变量中,然后对其进行操作,如果它不是 null

所以你应该联系提供这个库的团队并向他们提交错误。

假设 Context.ContentDatabase 和 Context.Database 是相同的类型。下面的代码应该可以工作。

var contentDatabase = Context.ContentDatabase ?? Context.Database;
if (fieldConfiguration == null && contentDatabase != null)
{
Item obj = contentDatabase.SelectSingleItem(
    string.Format("//*[@@templateid='{0}' and @@key='{1}']", 
        (object) TemplateIDs.TemplateField, (object) fieldName));
}