C# 4.0 重载接受“object”作为默认参数类型的方法

C# 4.0 重载接受“object”作为默认参数类型的方法,c#-4.0,overloading,C# 4.0,Overloading,我需要能够调用方法并传入未知类型的对象 然后调用正确的重载。我还需要一个接受 对象作为其参数类型。我看到的是,默认重载是唯一被使用的重载 以下是我试图做的要点: class Formatter { private object Value; public Formatter(object val){ Value = val; } public override string ToString() { return Format(Value); }

我需要能够调用方法并传入未知类型的对象 然后调用正确的重载。我还需要一个接受
对象
作为其参数类型。我看到的是,默认重载是唯一被使用的重载

以下是我试图做的要点:

class Formatter
{
  private object Value;

  public Formatter(object val){
    Value = val;
  }

  public override string ToString()
  {
    return Format(Value);
  }

  private string Format(object value)
  {
    return value.ToString();
  }

  private string Format(DateTime value)
  {
    return value.ToString("yyyyMMdd");
  }
}
好的,到目前为止还不错。现在我希望能够做到这一点:

public static class FancyStringBuilder()
{
  public static string BuildTheString()
  {
    var stringFormatter = new Formatter("hello world");
    var dateFormatter = new Formatter(DateTime.Now);
    return String.Format("{0} {1}", stringFormatter, dateFormatter);
  }
}
FancyStringBuilder.BuildTheString()
的结果是“hello world 2012-12-21 00:00:00.000”,而我预期的结果是“hello world 20121221”


问题是没有调用接受
DateTime
的重载,而是默认为接受
对象的重载我如何调用正确的方法而不使用混乱的switch语句?

我认为这是因为类构造函数将
对象
作为参数,然后将该对象分配给变量
,该变量也是
对象
。由于
Value
属于
object

试试这个

public override string ToString()
{
    if(Value is DateTime)
      return Format(Convert.ToDateTime(Value)); //this should call the right method

    return Format(Value); //works for other non-custom-format types e.g. String
}

Formatter.ToString()
中,总是调用覆盖
Formatter.Format(object)
。这是因为重载解析发生在编译时,而不是运行时。在编译时,关于
Value
唯一已知的是它是一个对象

如果您确实想区分传入类型,则需要在
格式化程序的构造函数中进行区分。在这种情况下,您可以立即调用
ToString()
,只存储格式化后的结果,而不是挂在对象上:

class Formatter
{
    string formattedValue;

    public Formatter(object value)
    {
        formattedValue = value.ToString();
    }

    public Formatter(DateTime value)
    {
        formattedValue = value.ToString("yyyyMMdd");
    }

    public string ToString()
    {
        return formattedValue;
    }
}
请注意,这确实假设您的对象在创建
格式化程序
对象和
格式化程序之间没有变化。调用ToString()
,或者至少可以在创建
格式化程序
时拍摄字符串表示的快照

这还假设您在编译时知道传入的类型。如果您想要一个真正的只运行时解决方案,那么必须使用“is”操作符或
typeof()
比较

如果您的目标只是基于传入类型提供自定义ToString()格式,我可能会使用从类型映射到格式字符串的列表:

static class Formatter
{
    private static List<Tuple<Type, string>> Formats;

    static Formatter()
    {
        Formats = new List<Tuple<Type, string>>();

        // Add formats from most-specific to least-specific type.
        // The format string from the first type found that matches
        // the incoming object (see Format()) will be used.
        AddMapping(typeof(DateTime), "yyyyMMdd");
        // AddMapping(typeof(...), "...");
    }

    private static void AddMapping(Type type, string format)
    {
        Formats.Add(new Tuple<Type, string>(type, format));
    }

    public static string Format(object value)
    {
        foreach (var t in Formats)
        {
            // If we find a type that 'value' can be assigned to
            // (either the same type, a base type, or an interface),
            // consider it a match, and use the format string.
            if (t.Item1.IsAssignableFrom(value.GetType()))
            {
                return string.Format(t.Item2, value);
            }
        }

        // If we didn't find anything, use the default ToString()...
        return value.ToString();
    }
}

这个例子不太管用。可能会出现24个左右的重载。我认为您应该只担心那些具有自定义格式的重载-从您的问题来看,这是唯一的日期。我最终选择了这种类型的解决方案。我尝试为每个格式化程序使用一个子类实现,但它对代码库的其余部分造成了很大的破坏。这是一个最简单的解决方案,而且扩展最少。我已经编辑了你的标题。请参阅“”,其中的共识是“不,他们不应该”。
Console.WriteLine(
    "{0} {1}",
    Formatter.Format(DateTime.Now),
    Formatter.Format("banana"));