方法重载对象和未指定的类型

本文关键字:类型 未指定 重载 对象 方法 | 更新日期: 2023-09-27 18:33:47

我有以下重载方法:

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

现在,如果我使用非类型化的 IEnumerable 调用该方法,其中包含 CustomClass,则调用 GetName(对象 obj(,为了解决这个问题,我像这样修改了该方法:

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

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

下面是调用 GetName(对象 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
}

请不要告诉我从我的自定义类中覆盖 ToString,请帮助我解决此方法调用问题。

方法重载对象和未指定的类型

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

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

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

编辑:为了处理递归方面的事情,您可能需要两个不同的名称,例如 GetNameGetNameImplGetName委托给GetNameImpl这就是所有有用的重载的调用。所以你会有:

// 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 - 例如,您可以让所有自定义类型实现特定接口,并在可用的地方使用它。

return GetName((dynamic)obj);

将过载解决推迟到运行时。

如果没有动态类型,支持双重调度的经典 OOP 解决方案(其中调用的方法取决于具有该方法的对象的具体类型和传递对象的具体类型(是访问者模式。

试试这个:

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