【问题标题】:C#: Generic method doesn't call specific method overloadC#:通用方法不调用特定方法重载
【发布时间】:2014-09-05 12:02:58
【问题描述】:

我正在尝试在 C# 中创建一个通用方法,它将根据其主体中的参数数据类型调用不同的方法,然后处理它们的结果。我试图通过创建一个通用包装方法来实现这一点,然后提供处理方法的几个重载 - 包括一个通用的,如果没有特定的重载可用。

当我直接调用处理方法时,正确选择了适当的版本。但是,当我从包装方法调用它时,它总是选择通用的,即使我传递给它的特定数据类型存在匹配的重载。

有什么方法可以调整代码以使其按我需要的方式运行?还是我必须使用不同的方法。

我需要代码与 Mono 2.6 兼容。

using System;

class Program
{
    static void Func<T>(T val)
    {
        Console.WriteLine("Generic Func");
    }

    static void Func(int val)
    {
        Console.WriteLine("Int Func");
    }

    static void Func(string val)
    {
        Console.WriteLine("String Func");
    }

    static void FuncWrap<T>(T val)
    {
        Console.Write("Wrap: ");
        Func(val);
    }

    static void Main(string[] args)
    {
        Func(2);
        Func("Potato");
        Func(2.0);

        FuncWrap(2);
        FuncWrap("Potato");
        FuncWrap(2.0);

        Console.Read();
    }
}

【问题讨论】:

  • 您也可以使用带有 int 和字符串的 FuncWrap 重载(或者直接使用 Func 方法而不进行包装)。

标签: c# generics mono unity3d polymorphism


【解决方案1】:

有什么方法可以纠正这种行为吗?

根据 C# 语言规范,这已经是正确的行为。在FuncWrap 中调用的Func 的重载通常在编译时确定,因此它不能根据执行时类型选择不同的Func 重载。

然而,改变行为的一种方法是使用动态类型:

static void FuncWrap<T>(T val)
{
    Console.Write("Wrap: ");
    dynamic x = val;
    Func(x);
}

现在将根据x 值的实际 类型在执行时执行重载决议。这会产生性能成本,但应该按照您的意愿去做。

或者,您可以对重载的知识进行硬编码:

static void FuncWrap<T>(T val)
{
    Console.Write("Wrap: ");
    if (typeof(T) == typeof(string))
    {
        Func((string)(object)val);
    }
    else if (typeof(T) == typeof(int))
    {
        Func((int)(object)val);
    }
    else
    {
        Func(val);
    }
}

这显然很可怕。

【讨论】:

  • 抱歉,我的措辞不正确。我的意思是“正确”,因为让它按照我需要的方式运行。动态似乎不适用于 Mono 2.6(我正在使用 Unity 引擎中的代码)。是的,第二种方法不可取,我正在寻找更清洁的方法(最好更快)。
  • @TomFroxiusMariank:查看 Mono 2.6 的发行说明,应该支持它 - 可能是 Unity 实际上将事情限制在较旧的配置文件中。 (它需要 .NET 4 配置文件。)如果没有 dynamic,你可能最好在我的回答结束时使用 hack ......这将表现得相当好(比动态更好,它基本上是使用反射)。您当然可以自己使用反射,但这不会很快。如果这些都不合适,您可能应该考虑重新设计。
  • 我明白了,我现在可能对当前 Unity 版本的 Unity 不走运,我会检查是否可以以某种方式更改配置文件,但我不确定那是否不会产生一些不良后果。如果它不起作用,我可能会重新编写代码以避免需要此功能。感谢您的帮助。
  • @TomFroxiusMariank 如果你不能使用 dunamic 并且不想做很多 ifs,你可以使用我为其他问题准备的课程:stackoverflow.com/questions/25662637/…。它允许您使用流利的 api 确定案例。你可以调整我的答案。我正在准备图书馆,所以你可以等待它,如果它符合你的要求。示例:obj.StronglyInvoke().When&lt;int&gt;(Func).When&lt;string&gt;(Func).Invoke();
猜你喜欢
  • 2020-07-28
  • 2010-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
相关资源
最近更新 更多