我来自C++背景,而且我对C#相对较新.目前,我正在尝试编写两个打印函数,第一个接受通用数组参数(并将数组的项打印到命令行),第二个接受通用基本参数(并调用其ToString()方法).这是我的代码:
using System;
namespace OverloadResolution
{
class Program
{
static void Main(string[] args)
{
string[] foo = new string[] { "A", "B", "C" };
Extensions.PrintMe(foo);
Extensions.PrintMe("Hello world");
Console.ReadLine();
}
}
public static class Extensions
{
public static void PrintMe<T>(T[] elm)
{
Console.WriteLine("PrintMe<T>(T[] elm)");
Console.WriteLine(string.Join("", elm));
}
public static void PrintMe<T>(T elm)
{
Console.WriteLine("PrintMe<T>(T elm)");
Console.WriteLine(elm.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
一切都按预期工作,并选择正确的重载.但是,如果我更改我的代码如下:
using System;
namespace OverloadResolution
{
class Program
{
static void Main(string[] args)
{
string[] foo = new string[] { "A", "B", "C" };
Extensions.PrintMe2(foo); // <<< Note the PrintMe2 function
Extensions.PrintMe2("Hello world"); // <<< Note the PrintMe2 function
Console.ReadLine();
}
}
public static class Extensions
{
public static void PrintMe2<T>(T elm)
{
PrintMe(elm);
}
public static void PrintMe<T>(T[] elm)
{
Console.WriteLine("PrintMe<T>(T[] elm)");
Console.WriteLine(string.Join("", elm));
}
public static void PrintMe<T>(T elm)
{
Console.WriteLine("PrintMe<T>(T elm)");
Console.WriteLine(elm.ToString());
}
}
}
Run Code Online (Sandbox Code Playgroud)
调用PrintMe2函数时类型信息似乎丢失了,因为在内部,PrintMe在两种情况下都会调用第二个函数.在这种情况下是否有适用的特殊规则?或者我错过了什么?我使用C#7.0和.NET framework 4.7.我应该注意到,我已经了解到与C++模板相比,C#泛型的使用非常有限......
在PrintMe2编译时,我们必须执行重载决策以确定PrintMe调用哪个方法,并且我们必须将正确的方法标记发送到PrintMe2s IL以识别该方法.
在PrintMe2编译时,我们不知道其T类型参数的性质.它可能是任何东西.唯一PrintMe不受限制的版本是PrintMe<T>(T elm).因此,我们将特定方法的方法标记发送到IL中.
泛型与模板不同,最显着的是因为它们是与可能使用它们的任何代码分开编译的.我们必须在作出决定他们的编译时间,以及这些决定必须为所有可能的类型参数是有效的(受应用于类/方法,其中类型参数(一个或多个)声明任何类型的约束)
如果你想要一个只根据传入的参数的运行时类型进行重载解析的方法,你可以使用dynamic,但这很难看并带来很多开销.它也可能导致运行时错误,没有特定的重载是某些用例最特殊的.
| 归档时间: |
|
| 查看次数: |
117 次 |
| 最近记录: |