【问题标题】:Function with IFormattable parameter won't accept a String带有 IFormattable 参数的函数不接受字符串
【发布时间】:2013-11-12 20:59:48
【问题描述】:

我有一个处理字符串输入的函数。

    public string Foo(string text)
    {
        // do stuff with text and
        // return processed string
    }

我在很多地方都在调用它,我将 guid 转换为这样的字符串:

string returnValue = Foo(bar.ToString());

我真正想要的是接受任何可以转换为字符串的对象类型作为输入。于是我尝试修改函数如下:

    public string Foo(IFormattable text)
    {
        var textAsString = text.ToString();
        // do stuff with textAsString 
        // and return processed string
    }

这意味着我所有的调用都更简单了:

string returnValue = Foo(bar);

它适用于所有具有 .ToString 方法的对象类型;除了字符串:)

如果我尝试将字符串传递给函数,我会收到以下编译错误:

Argument type 'string' is not assignable to parameter type 'System.IFormattable'  

这看起来很奇怪,因为 String 有一个 ToString() 方法。

为什么这不起作用?

【问题讨论】:

    标签: c# .net iformattable


    【解决方案1】:

    简单地说,System.String 没有实现 IFormattable。

    如果文档对您来说还不够:

    object x = "a string";
    Console.WriteLine(x is IFormattable); // False
    

    鉴于ToString() is declared on object,为什么不直接拥有:

    public string Foo(object text)
    {
        var textAsString = text.ToString();
        // do stuff with textAsString 
        // and return processed string
    }
    

    确实,ToString() method declared by IFormattable 并不是您试图调用的那个 - 您没有传递格式字符串或格式提供程序。

    另外:

    这看起来很奇怪,因为 String 有一个 ToString() 方法。

    接口不是鸭式的。仅仅因为一个类型具有接口所需的所有成员并不意味着它实现了该接口。

    【讨论】:

      【解决方案2】:

      String 没有实现IFormattable,但你的代码也没有使用它。您可以为 string 创建一个包装器类,以便在需要 IFormattable 的场景中使用,如下所示:

      public class FormattableString : IFormattable {
          private readonly string str;
          public FormattableString(string str) {
              this.str = str;
          }
          public string ToString() {
              return str;
          }
          public string ToString(string format, IFormatProvider formatProvider) {
              // You can add special code here to format the value of your string
              // as directed by the format passed into the method.
              return str;
          }
      }
      

      现在你可以按如下方式使用这个类:

      string returnValue = Foo(new FormattableString(bar));
      

      【讨论】:

      • 我认为没有参数的 ToString() 是不必要的(如果存在应该有“覆盖”)。但否则这正是我想要的,谢谢!
      【解决方案3】:

      首先,IFormatable 没有实现.ToString(),它只实现了.ToString(string, IFormatProvider)。掌握了这些知识后,如果您仍想使用 IFormatable,最简单的处理方法就是为您的方法使用重载。

      public string Foo(IFormattable text, string format, IFormatProvider formatProvider)
      {
          return Foo(text.ToString(format, formatProvider));
      }
      
      public string Foo(IFormattable text, string format)
      {
          return Foo(text.ToString(format, null));
      }
      
      public string Foo(string text)
      {
          // do stuff with text and
          // return processed string
      }
      

      【讨论】:

        猜你喜欢
        • 2013-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-11
        • 1970-01-01
        • 1970-01-01
        • 2017-05-23
        • 1970-01-01
        相关资源
        最近更新 更多