【问题标题】:Call overloaded generic method from generic method从泛型方法调用重载的泛型方法
【发布时间】:2020-05-31 10:01:29
【问题描述】:

我的问题是:为什么从未调用过 AddData(string data)?当我调用ds.Add("Some text") 时,data 参数的类型在编译时是已知的,因此Add 的重载实现应该调用AddData(string) 方法(或者这是我所希望的)

输出是

Ignore data of type System.String
Ignore data of type System.Double
using System;

namespace GenericCall
{
    interface IDataStore
    {
        void Add<T>(T data);
    }

    class MyDataStore : IDataStore
    {
        public void Add<T>(T data)
        {
            AddData(data);
        }

        private void AddData<T>(T data)
        {
            Console.WriteLine($"Ignore data of type {data.GetType()}");
        }

        private void AddData(string data)
        {
            Console.WriteLine("Accept string data");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyDataStore ds = new MyDataStore();
            ds.Add("Some text");
            ds.Add(3.14);
        }
    }
}

【问题讨论】:

  • 您基本上希望Add 根据参数类型调用两种不同方法之一。简短的回答 - 编译器不会做你希望它做的事情。它在编译时选择最佳匹配 (AddData&lt;T&gt;) 并总是调用它。它这样做基本上是为了简单 - 因为它在编译时无法知道它是否会被 string 或 int 或其他什么调用。

标签: c# generics overloading


【解决方案1】:

重载解决发生在代码的编译时。

在编译时,编译器并不知道T 究竟是什么,所以这个调用:

public void Add<T>(T data)
{
    AddData(data); <------
}

只能解析为通用的AddData,根据rules of overload resolution。

在运行时进行重载解析的一种方法是让公共 Add 接受 dynamic 参数:

// you should change the interface declaration also!
public void Add(dynamic data)
{
    AddData(data);
}

这将产生输出:

Accept string data
Ignore data of type System.Double

【讨论】:

  • @Sweeper 非常感谢!我开始考虑手动反射,但使用dynamic 对我有用。但只是为了确定。当我调用Add("text") 和Add(1.23) 时,编译器只生成一个方法Add,对吧?否则它可能更适合 AddData 并调用适当的版本。
  • @user2146414 是的,IL 中只有一个 Add 方法。 Learn more here。也就是说,dynamic 应该谨慎使用。我的示例只是为了向您展示运行时的重载解决方案是什么样的。在不了解您的情况的情况下,我不确定这是否是对动态的适当使用。我建议你先阅读this。
猜你喜欢
  • 1970-01-01
  • 2011-04-23
  • 2011-05-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-09
相关资源
最近更新 更多