【问题标题】:How can I get the string interpolation operator $ to print "null" for null parameters?如何让字符串插值运算符 $ 为空参数打印“null”?
【发布时间】:2020-11-05 04:28:32
【问题描述】:
string o=null;
Console.WriteLine($"Hello World '{o}'");

这个输出:

你好世界''

我想为空值明确写“null”。

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

这就是这样做的:

Hello World 'null'

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

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

编译错误运算符'??'不能应用于“数组”和“字符串”类型的操作数

实现预期结果的最佳方法是什么?很遗憾,您无法修改 $ 处理 null 的方式,因为它似乎硬编码为使用 String.EmptyString

【问题讨论】:

  • $"{o?.ToString() ?? "null"}"?
  • @juharr 呸!这似乎抵消了$ 的全部好处。可以以某种方式将其拉出到实用程序方法中吗?很遗憾,您无法修改 $ 处理 null 的方式,因为它似乎硬编码为使用 String.EmptyString
  • @Mr.Boy 好吧,输出“null”不是常见的要求。这通常不是您希望最终用户看到的词。
  • 即使你这样做了,你也可以随时覆盖 ToString
  • @Mr.Boy 你总是可以把它变成一个扩展方法并调用它,即public static string ToStringWithNullOutput(this object input) => input is null ? "null" : input.ToString(); 然后你的调用代码在语义上是清晰的,没有人会得到意外的行为。 Console.WriteLine($"Hello World '{oToStringWithNullOutput()");

标签: c# null conditional-operator string-interpolation null-coalescing-operator


【解决方案1】:

如果您的变量不为空,我不确定您要打印什么,但您可以尝试ternary conditional operator

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

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

取决于o 是什么以及您是否覆盖了ToString()


相关:

How to print the null values if the dictionary has it using LINQ

【讨论】:

    【解决方案2】:

    您可以利用 $ 将您的字符串转换为 formattablestring,并且您可以提供一个自定义格式,它将在依次处理每个 arg 时调用。就像为排序函数提供自定义比较器一样

    
    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();
            }
        }
    }
    
    

    您可以通过将它传递给一个函数来触发您的 null 格式提供程序,该函数将使 c# 将其视为可格式化的字符串(而不是编译器直接调用字符串格式):

    static string NullyVersion(FormattableString formattable)
    {
        return formattable.ToString(new NullyFormatProvider());
    }
    
    ...
    
    Array o = null;
    string txt = NullyVersion($"check out this array: {o}");
    
    

    当然,你不会让它这么长/你可能不会使用 NullyVersion 创建一个字符串来使用你想要的字符串.. 你会做你的例如“采用字符串的日志记录方法”采用 FormattableString 代替,然后使用 nully 格式化程序对其进行格式化,可能如下:

    static string Log(FormattableString formattable)
    {
        Console.WriteLine( formattable.ToString(new NullyFormatProvider()); //or some instance of NFP
    }
    

    然后你可以像一开始想要的那样在你的代码中使用:

    Array o = null;
    Log($"Data was {o}");
    

    我还没有深入研究如何检查您是否传递了采用格式的东西 - 您会注意到 ICustomFormatter 中的 Format() 方法采用 string format - 如果您编写了 Log($"it is now {DateTime.Now:yyyyMMdd} woo")那么object arg 将是日期时间,string format 将包含"yyyyMMdd" - 它可以是您想要的任何东西。您可以定义自己的:

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

    并以您的格式:

    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()));
    

    更多详情请查看 ICustomFormatter https://docs.microsoft.com/en-us/dotnet/api/system.icustomformatter?view=netcore-3.1

    【讨论】:

    • 我很想知道为什么这在没有解释的情况下被否决了,写这篇文章的工作量不小,
    • 我们可能永远也不会发现;关于“关于可以改进什么的评论是否应该是强制投放 DV”的辩论是漫长的,而且是一圈又一圈。这可能是因为我没有回答你的问题这样微不足道的事情,因为我没有编写一个准确且仅返回“null”的格式化程序。最重要的是希望回答您的问题并让您知道“不,您不必忍受默认格式化程序 - 您可以编写自己的”。在您的对象不为空的所有情况下,您甚至可以推迟到默认值,并在它为空时返回“空”..
    【解决方案3】:

    您可以将"null" 强制转换为object,以便?? 可以应用于所有类型的操作数。

    $"Hello World '{o ?? (object)"null"}'"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-22
      • 2018-07-10
      • 2012-01-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-18
      • 1970-01-01
      相关资源
      最近更新 更多