- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我想知道是否有可能以某种方式在 C# 中专门化通用接口(interface)方法?我发现了类似的问题,但没有完全像这样的问题。现在我怀疑答案是“不,你不能”,但我想确认一下。
我有类似下面的内容。
public interface IStorage
{
void Store<T>(T data);
}
public class Storage : IStorage
{
public void Store<T>(T data)
{
Console.WriteLine("Generic");
}
public void Store(int data)
{
Console.WriteLine("Specific");
}
}
class Program
{
static void Main(string[] args)
{
IStorage i = new Storage();
i.Store("somestring"); // Prints Generic
i.Store(1); // Prints Generic
Storage s = (Storage)i;
s.Store("somestring"); // Prints Generic
s.Store(1); // Prints Specific
}
}
有没有办法让它在接口(interface)调用的时候使用专门版本的Store?如果不是,有人知道 C# 以这种方式处理泛型参数的确切原因吗?
编辑:如果不是因为 C# 无法在多个步骤中解析模板参数,则可以解决该问题。
void Foo<T>(T t)
{
SubFoo(t);
}
void SubFoo<T>(T t)
{
Console.WriteLine("Generic");
}
void SubFoo(int t)
{
Console.WriteLine("Specific");
}
在这里调用 Foo(1) 也会打印“Generic”,难道编译器不能解决这个问题吗?还是 JIT 会阻止这种情况?
最佳答案
重载解析是在编译时执行的,而不是在运行时根据传递值的实际类型执行的。
IStorage i = new Storage();
i.Store("somestring"); // Prints Generic
i.Store(1); // Prints Generic
这将始终调用“通用”方法,因为 IStorage
中只有一个 Store
重载,编译器不知道 i
实际上包含一个 Storage
对象。编译器如何知道 Storage
中的其他重载?
Storage s = (Storage)i;
s.Store("somestring"); // Prints Generic
s.Store(1); // Prints Specific
在这里,编译器知道 s
包含一个 Storage
对象(或从 Storage
派生的对象),因为 s
就是这样声明的。所以它看到两个重载。它为 int
值选择特定的重载,因为重载解析规则表明优先选择特定的重载而不是通用的重载。
技术上可以在运行时确定泛型方法中的 typeof(T)
并将方法调用转发给特定方法。但仔细想想,这并没有多大意义。通用方法意味着相同的实现适用于不同的、不相关类型的参数。如果您想要不同类型的不同实现,则不应为此使用泛型。
void Foo<T>(T t)
{
SubFoo(t);
}
void SubFoo<T>(T t);
void SubFoo(int t);
泛型的工作方式与 C++ 模板有很大不同。 C# 编译器仅将 Foo 编译一次——编译为通用方法。请记住:通用意味着不同类型的相同实现。 C# 编译器在编译时不知道 T 是 int
还是 string
或任何其他类型。因此,适用于任何 T 的 Foo 的唯一可能实现是调用 SubFoo
关于C# 泛型接口(interface)特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2229084/
我是一名优秀的程序员,十分优秀!