简体   繁体   English

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

[英]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: 现在,如果我使用拥有CustomClass的无类型IEnumerable调用该方法,则将调用GetName(object obj)来解决此问题,我修改了如下方法:

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? 我认为编写20条IF语句并捕获所有其他可能性非常烦人,是否有一种更简单的方法可以使用无类型的IEnumerable枚举来调用正确的重载?

Here is the code that calls the GetName(object obj): 这是调用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. 请不要告诉我从CustomClass覆盖ToString,帮助我解决此方法调用问题。

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. 编辑:要处理事情的递归方面,您可能想要两个不同的名称,例如GetNameGetNameImpl ,其中GetName委托给GetNameImpl ,这就是所有有用的重载都被调用的地方。 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). 如果希望调用者能够直接调用重载,则可以将动态的一个重命名为GetNameDynamic ,而其他的重命名为GetName (并将它们公开)。

I rarely find that dynamic is a good solution, but it would avoid the code duplication. 我很少发现, dynamic是一个很好的解决方案,但它避免代码重复。 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. 您不必重写ToString您可以使所有自定义类型实现特定的接口,并在可用的情况下使用该接口。

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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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