void LoadParameters<TValue>(Type i1, TValue i2)
where TValue : i3;
{
Tvalue A;
看到这段代码,我稍微修改了它的专有
我在想是否与
相同void LoadParameters(Type i1, TValue i2)
{
i3 A;
由于开发人员已经知道A是i3类型,而不只是在代码中指定了吗?
答案 0 :(得分:2)
你的假设是错误的:
由于开发人员已经知道
A
属于i3
类型,而不只是在代码中指定了吗?
TValue
可以是i3
或任何派生!如果i3
是一个接口,您可以像这样调用方法:
LoadParameters<i3>(...);
或使用任何实现i3
的类型:
class Foo : i3 { }
interface IBar { }
class FooBar : Foo, IBar { }
LoadParameters<Foo>(...); // Okay
LoadParameters<IBar>(...); // fails, because IBar does not inherit from i3!
LoadParameters<FooBar>(...); // Okay, because FooBar inherits from Foo that implements i3!
如果您错误地调用LoadParameters
(如第二个示例中所示),则编译器会抱怨它。如果不使用约束,您将遇到运行时异常,这些异常更难调试。因此,通过支持开发人员以正确的方式调用方法,而不是遇到异常并让他修复代码,约束有助于使代码更具可读性。
答案 1 :(得分:1)
在编译时是否会推断出一些void LoadParameters<TValue>
,因此您可以利用泛型类型
考虑第一个版本,因为您可以使用相同的通用代码加载任何类型的参数,而无需在每次需要获取新类型时创建更多版本
答案 2 :(得分:0)
解释了C#中类型参数的限制here。在您的情况下,TValue
可以采用在第一种情况下i3
派生的任何类型,其中第二种情况A
将完全属于i3
类型。
答案 3 :(得分:0)
从调用者的角度来看,你是对的 - 实际上它写得非常相似:
1. LoadParameters<TValue>( Type v1, TValue v2 ) where TValue : Interface3;
or
2. LoadParameters( Type v1, Interface3 v2 );
它没有什么区别 - 当调用method2时,编译器将检查提供的参数是否可以转换为Interface3(与泛型类型参数完全相同),如果你想要确定你的Object的语法糖不仅可以使用Interface3,而且可以从某个子类同样调用:
1. LoadParameters<Foo>( v1, v2 );
2. LoadParameters( v1, (Foo)ve ); // Explicit Casting provides static type-checking
soooo ....区别在哪里?为什么我们甚至需要泛型?
答案不在于签名,而在于Method ...想象一下,你想在Method中构造一个新的Object,或者创建一个通用的List。 - 使用Generic TValue ,您可以轻松调用TValue-&gt; newInstance()或创建List。想象一下Generic类型作为第三个参数,你可以获得一个额外的Class-Information,它不需要是v2的运行时类,但v2必须可以转换为该类......