简体   繁体   中英

Method overloads object and unspecified type

I have the following method with an overload:

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

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

Now if I call the method with an untyped IEnumerable wich holds CustomClass the GetName(object obj) gets called, to fix this I have modified the method like this:

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

    return obj.ToString();
}

I think its rather annoying to write 20 IF statements and catch all the other possibilities, is there an easier way to call the correct overload with an untyped IEnumerable enumeration?

Here is the code that calls the 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
}

Pls dont tell me to override ToString from my CustomClass, help me fix this method calling problem.

Well, you could use dynamic typing . That will basically defer overload resolution until execution time:

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

Note that there's potentially a performance cost here - it may well be minimal and insignificant, but it's worth being aware of.

EDIT: To handle the recursion side of things, you'd probably want two different names, eg GetName and GetNameImpl where GetName delegates to GetNameImpl which is what all the useful overloads are called. So you'd have:

// 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?
}

Note that there's a potential problem with this: if you have two overloads for different interfaces and one type implements both interfaces (but there isn't a specific overload for that type itself) then you'll get an exception at execution time.

If you want callers to be able to call the overloads directly, you could just rename the dynamic one to GetNameDynamic and the others to GetName for example (and make them public).

I rarely find that dynamic is a good solution, but it would avoid the code duplication. I would try to step back and find a different design to be honest. You explicitly rejected it in the question, but polymorphism is the preferred way of handling this. You don't need to necessarily override ToString - you could make all of the custom types implement a particular interface, and use that where it's available, for example.

return GetName((dynamic)obj);

将重载解析推迟到运行时。

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

Try this:

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

    return obj.ToString();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM