C# 如何让字符串插值运算符$为空参数打印“null”?

C# 如何让字符串插值运算符$为空参数打印“null”?,c#,null,conditional-operator,string-interpolation,null-coalescing-operator,C#,Null,Conditional Operator,String Interpolation,Null Coalescing Operator,这将产生: 你好,世界 我想显式地为空值编写null string o=null; Console.WriteLine($"Hello World '{o}'"); 这就是: 你好,世界“空” 但如果o不是string或Object类型,则会生成编译错误。例如: string o=null; Console.WriteLine($"Hello World '{o??"null"}'"); 编译错误运算符“??”不能应用于“数组”和“

这将产生:

你好,世界

我想显式地为空值编写null

string o=null;
Console.WriteLine($"Hello World '{o}'");
这就是:

你好,世界“空”

但如果o不是string或Object类型,则会生成编译错误。例如:

string o=null;
Console.WriteLine($"Hello World '{o??"null"}'");
编译错误运算符“??”不能应用于“数组”和“字符串”类型的操作数

实现预期结果的最佳方式是什么?很遗憾,您无法修改$处理null的方式,因为它似乎是硬编码为使用String.EmptyString的。您可以将null强制转换为object,以便??可以应用于所有类型的操作数

Array o=null;
Console.WriteLine($"Hello World '{o??"null"}'");

您可以利用$将字符串转换为formattablestring,还可以提供一个自定义的格式化字符串,当它依次处理每个参数时将调用该字符串。类似于为排序函数提供自定义比较器

$"Hello World '{o ?? (object)"null"}'"
您可以通过将null格式提供程序传递给一个函数来触发它,该函数将使c将其视为可格式化的字符串,而不是编译器直接调用的字符串格式。例如:


class NullyFormatProvider : IFormatProvider
{
    private readonly NullyFormatter _formatter = new NullyFormatter();

    public object GetFormat(Type formatType)
    {
        if (formatType == typeof(ICustomFormatter))
            return _formatter;
        return null;
    }

    class NullyFormatter : ICustomFormatter
    {
        public string Format(string format, object arg, IFormatProvider formatProvider)
        {
            if (arg == null)
                return "arg was null, bro!";
            else
                return arg.ToString();
        }
    }
}

当然,您不会让它这么长/您可能不会使用NullyVersion来创建要在需要字符串的位置使用的字符串。。您可以让您的日志记录方法(例如,采用字符串的日志记录方法)改为采用FormattableString,然后使用nully格式化程序对其进行格式化,可能类似于:

static string NullyVersion(FormattableString formattable)
{
    return formattable.ToString(new NullyFormatProvider());
}

...

Array o = null;
string txt = NullyVersion($"check out this array: {o}");

然后,您可以在代码中使用您一开始想要的内容:

static string Log(FormattableString formattable)
{
    Console.WriteLine( formattable.ToString(new NullyFormatProvider()); //or some instance of NFP
}
我还没有深入研究如何检查是否传递了采用格式的内容-您会注意到ICustomFormatter中的format方法采用字符串格式-如果您编写的日志$it now是{DateTime.now:yyyyMMdd}woo,则对象arg将是DateTime,字符串格式将包含yyyyMMdd-它可以是您想要的任何内容。您可以定义自己的:

Array o = null;
Log($"Data was {o}");
以您的格式:

int[] nums = {1,2,3};
Log($"those nums are {nums:csv}");

有关更多详细信息,请查看ICustomFormatter

如果变量不为null,我不确定要打印什么,但您可以尝试

取决于o是什么,以及您是否已重写ToString

相关的:


${o?.ToString??null}?@juharr恶心!这似乎抵消了美元的全部好处。这是否可以用一种实用的方法解决呢?很遗憾,您无法修改$null的处理方式,因为它似乎是硬编码的,使用字符串。EmptyString@Mr.Boy嗯,输出null不是一个常见的要求。这通常不是你希望最终用户看到的一个词。即使你看到了,你也可以覆盖它ToString@Mr.Boy您总是可以将其设为扩展方法并调用它,而不是ie public static string to stringwithnulloutput this object input=>input为null?null:input.ToString;那么您的调用代码在语义上就很清楚了,没有人会得到意外的行为。Console.WriteLine$Hello World'{oToStringWithNullOutput;我很感兴趣的是为什么这篇文章没有解释就被否决了,写这篇文章需要做大量的工作,我们可能永远也找不到答案;关于是否对可以改进的内容进行评论应该强制投DV的争论是冗长的,而且是反复的。这可能是为了一些我没有回答的琐碎事情我们的问题是因为我没有编写一个只返回null的格式化程序。最重要的是希望回答您的问题,并让您知道不,您不必忍受默认的格式化程序-您可以自己编写。在所有情况下,您甚至可以在对象不为null且仅为r的情况下使用默认的格式化程序设置为..时返回空值。。
if(format == "csv" && arg is int[] x)
  //turn the passed in arg (an int array inside an obj) into some csv representation...
  return string.Join(",", x.Select(e => e.ToString()));
Array o = null;
Console.WriteLine($"Hello World '{(o == null ? "null" : "not null")}'");
Array o = null;
Console.WriteLine($"Hello World '{(o == null ? "null" : o.ToString())}'");