0

我有以下重载方法:

public string GetName(object obj)
{
    return obj.ToString();
}

public string GetName(CustomClass cc)
{
    return cc.Name + " - " + cc.Description;
}

现在,如果我使用无类型的 IEnumerable 调用该方法,该方法包含 CustomClass,则调用 GetName(object obj),为了解决此问题,我修改了如下方法:

public string GetName(object obj)
{
    if (obj is CustomClass)
        return GetName(obj as CustomClass);

    return obj.ToString();
}

我认为编写 20 条 IF 语句并捕捉所有其他可能性相当烦人,有没有更简单的方法来使用无类型的 IEnumerable 枚举调用正确的重载?

下面是调用 GetName(object obj) 的代码:

IEnumerable rawData = GetData(); //DataBase method that fetches a CustomClass

foreach (var rawDataItem in rawData)
{
    Debug.Print(GetName(rawDataItem)); //calls the GetName(object obj) overload
}

请不要告诉我从我的 CustomClass 覆盖 ToString,帮我解决这个方法调用问题。

4

4 回答 4

6

好吧,你可以使用动态类型。这基本上会将重载解决方案推迟到执行时间:

foreach (dynamic rawDataItem in rawData)
{
    Debug.Print(GetName(rawDataItem));
}

请注意,这里可能存在性能成本 - 它可能很小且微不足道,但值得注意。

编辑:要处理事物的递归方面,您可能需要两个不同的名称,例如GetName,所有有用的重载都GetNameImpl在哪里调用。所以你会有:GetNameGetNameImpl

// Note that dynamic as a parameter type is equivalent to object for callers.
// The dynamic part is only relevant within the method.
public string GetName(dynamic obj)
{
    return GetNameImpl(obj);
}

// Fallback when no other overloads match
private string GetNameImpl(object obj)
{
    ...
}

private string GetNameImpl(IEnumerable obj)
{
    // Maybe build up the name by calling GetName on each element?
}

请注意,这有一个潜在的问题:如果您有两个不同接口的重载,并且一个类型实现了这两个接口(但该类型本身没有特定的重载),那么您将在执行时遇到异常。

如果您希望调用者能够直接调用重载,您可以将动态的重命名为GetNameDynamic,将其他重命名GetName为例如(并将它们公开)。

我很少发现这是一个好的解决方案dynamic,但它可以避免代码重复。老实说,我会尝试退后一步,找到不同的设计。您在问题中明确拒绝了它,但多态性处理此问题的首选方式。您不一定需要重写- 例如,您可以使所有自定义类型实现特定接口,并在可用的地方使用它。ToString

于 2013-10-04T06:05:09.813 回答
1
return GetName((dynamic)obj);

将重载决议推迟到运行时。

于 2013-10-04T06:06:06.120 回答
0

在没有动态类型的情况下,支持双重分派的经典 OOP 解决方案(调用的方法取决于具有该方法的对象的具体类型和传递的对象的具体类型)是访问者模式

于 2013-10-04T06:13:47.393 回答
0

尝试这个:

public string GetName(object obj)
{
    if (!(obj is IEnumerable<object>))
        return GetName(obj as CustomClass);

    return obj.ToString();
}
于 2013-10-04T06:19:14.633 回答