gpt4 book ai didi

C# 泛型接口(interface)特化

转载 作者:可可西里 更新时间:2023-11-01 07:44:52 31 4
gpt4 key购买 nike

我想知道是否有可能以某种方式在 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 。如果根据 T 调用 SubFoo 重载之一,则 Foo 的实现对于所有 T 将不再相同。

关于C# 泛型接口(interface)特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2229084/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com