【问题标题】:What causes exception in string.concat是什么导致 string.concat 中的异常
【发布时间】:2011-06-02 22:45:37
【问题描述】:

这里有几个类:

public class MyItem : ParamOut
{
    public string Code
    {
        get { return _quoteCode; }
    }

    public InnerItem[] Skus
    {
        get { return _skus; }
    }

    public PriceSummary Price
    {
        get { return _price; }
    }

    public override string ToString()
    {
        return string.Concat("Code=", Code, "; SKUs=[", Skus != null ? "{" + string.Join("},{", Array.ConvertAll(Skus, item => item.ToString())) + "}" : "", "]"
            , "; Price={", Price.ToString(), "}", base.ToString()
            );
    }

    ...
}

public abstract class ParamOut
{
    public override string ToString()
    {
        return null;
    }

    public string ErrorMessage { get; set; }
}

这里是调用功能:

{
    MyItem item = new MyItem{ ErrorMessage = "Bla-bla-bla" };
    string text = item.ToString();
}

我在“ToString()”方法中得到 NullReference 异常(项目变量的每个属性都是空的)。

问题:

第一季度。在这种情况下会调用什么重载的 string.Concat?我有 9 个参数,所以我猜是以下之一:

public static string Concat(params Object[] args)

public static string Concat(params string[] values)

但是他们中的哪一个?

第二季度。为什么会产生异常? 'null'不应该被转换成'null'或“”(空字符串)之类的东西吗?

非常感谢!

【问题讨论】:

  • 您能否发布完整的回溯以及可能导致其抛出的一些示例执行?我猜你在三元运算符内的item.ToStringPrice.ToString()base.ToString() 上遇到了空异常,而Concat 本身不是在对空进行吐槽。

标签: .net string concatenation string-concatenation


【解决方案1】:

不应将 'null' 转换为 类似“null”或“”(空 字符串)?

它应该转换成什么?有些人喜欢空字符串,有些人喜欢“null”等。微软决定不回答这个问题,因为这里有很多东西是有效的答案。所以MS采取了更安全的路线,只是抛出了一个异常。

【讨论】:

  • 为了清楚起见,导致异常的是空引用上的 .ToString() 调用,而不是将空值传递给Concat
  • 确实如此。但是Concat 仍然没有检查参数是否为空,然后将其作为特殊情况处理,所以从某种意义上说,我的回答仍然有效。 MS 决定不处理空值的串联。
  • Concat(params string[] values) 方法中,如果单个字符串为空,则视为空。 msdn.microsoft.com/en-us/library/system.string.concat.aspx "使用空字符串代替数组中的任何空对象"
【解决方案2】:
  1. 我猜是调用了 'Object[]' 的重载(因为使用了不同类型的参数)(如果我错了请纠正我)。

  2. 如果 Price 为空,Price.ToString() 会导致错误。而且这里根本不需要 .ToString()

【讨论】:

    【解决方案3】:
    1. 最合适的重载 - 如果所有参数都是字符串,则将调用字符串重载。因为它们不是,所以将调用 Object 重载。

    2. Price 可能是 null 或 SKU 项目之一,甚至是 Code,因此在其中任何一个上调用 ToString(将对象传递给 Concat 将调用 ToString)抛出 NullReferenceException。

    【讨论】:

      【解决方案4】:

      q1:你只传入字符串,所以它将使用 string[] 版本

      q2:除了 matt 所说的,即使 Concat 允许 null 值,您仍然会从调用 Price.ToString() 的地方得到异常,因为 Price 为 null

      【讨论】:

        【解决方案5】:

        首先,我怀疑你的NullReferenceException 是因为你在一个空对象上调用ToString

        但是,尝试连接 null 也会给您该异常。

        在这种情况下,您可能更喜欢使用string.Format

        return string.Format("Code={0}; SKUs=[{1}]; Price={2}{3}", 
            Code ?? "null",
            SKUs != null ? 
                string.Join(",", SKUs.Select(s => "{" + s.ToString() ?? "null" + "}")) :
                string.Empty,
            (Price ?? "null").ToString() ?? "null",
            base.ToString() ?? "null");
        

        您可以在任何可能处理空值的地方看到空合并运算符 (??) 的使用。

        x.ToString() ?? "null"
        

        逻辑上等价于

        x.ToString() == null ? "null" : x.ToString()
        

        我对有多少空检查有点过头了,但看起来你的代码中有很多潜在的陷阱。 :)

        【讨论】:

        • 如果 x 为空,x.ToString() ?? "null" 将转换为 NullReferenceException
        • 是的,您可以看到我处理的是“价格”,但不是 SKU 列表。
        • 确保您自己的 ToString 方法永远不会返回 null 也很有帮助,这样您就可以检查基础对象(即 (Price ?? "null").ToString ()) 本身而不是每个 ToString 调用。
        【解决方案6】:

        我想你自己说的:

        (item变量的每个属性都为null)

        您可能应该检查InnerItems 的数组(来自Skus 属性)是否包含任何null 元素。

        可以通过简单的Where-clause 或类似的语句来避免它们。

        并回答您的问题:

        • Q1:string[] 重载将被调用。
        • Q2:Concat 会将null 视为空字符串。

        【讨论】:

          猜你喜欢
          • 2014-11-07
          • 1970-01-01
          • 2011-09-30
          • 2016-06-30
          • 2010-10-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多