C# C语言中的动态和泛型#

C# C语言中的动态和泛型#,c#,c#-4.0,generics,C#,C# 4.0,Generics,正如在C 3.5中发现的,由于类型擦除,以下情况不可能发生:- int foo<T>(T bar) { return bar.Length; // will not compile unless I do something like where T : string } foo("baz"); intfoo(T条) { return bar.Length;//将不会编译,除非执行类似于where T:string的操作 } 富(baz);; 我相信这不起作用的原因是在

正如在C 3.5中发现的,由于类型擦除,以下情况不可能发生:-

int foo<T>(T bar)
{
    return bar.Length; // will not compile unless I do something like where T : string
}

foo("baz");
intfoo(T条)
{
return bar.Length;//将不会编译,除非执行类似于where T:string的操作
}
富(baz);;
我相信这不起作用的原因是在C#和java中,是由于一个称为类型擦除的概念,请参阅

读过这个关键词后,我写了以下内容:-

int foo<T>(T bar)
{
    dynamic test = bar;
    return test.Length;
}

foo("baz"); // will compile and return 3
intfoo(T条)
{
动态试验=杆;
返回测试。长度;
}
foo(“baz”);//将编译并返回3
因此,据我所知,dynamic将绕过编译时检查,但如果类型已被擦除,它肯定仍然无法解析符号,除非它更深入并使用某种反射


以这种方式使用dynamic关键字是一种糟糕的做法吗?这是否会使泛型更强大一些?

动力学和泛型是两个完全不同的概念。如果您想要编译时的安全性和速度,请使用强类型(泛型或标准OOP技术,如继承或组合)。如果您在编译时不知道该类型,则可以使用dynamics,但由于使用的是运行时调用,因此它们的速度会较慢,并且安全性会降低,因为如果该类型未实现您尝试调用的方法,则会出现运行时错误

这两个概念不能互换,根据您的具体要求,您可以使用其中一个

当然,具有以下泛型约束是完全无用的,因为
string
是密封类型,不能用作泛型约束:

int foo<T>(T bar) where T : string
{
    return bar.Length;
}

动力学和泛型是两个完全不同的概念。如果您想要编译时的安全性和速度,请使用强类型(泛型或标准OOP技术,如继承或组合)。如果您在编译时不知道该类型,则可以使用dynamics,但由于使用的是运行时调用,因此它们的速度会较慢,并且安全性会降低,因为如果该类型未实现您尝试调用的方法,则会出现运行时错误

这两个概念不能互换,根据您的具体要求,您可以使用其中一个

当然,具有以下泛型约束是完全无用的,因为
string
是密封类型,不能用作泛型约束:

int foo<T>(T bar) where T : string
{
    return bar.Length;
}

在这种情况下,您将无法从动力学中获得任何好处。您只需延迟错误,因为如果动态对象不包含
Length
属性,就会引发异常。在使用泛型方法访问
Length
属性的情况下,我看不出有任何理由不将其限制为明确具有此属性的类型。

在这种情况下,您将无法从动力学中获得任何好处。您只需延迟错误,因为如果动态对象不包含
Length
属性,就会引发异常。如果在泛型方法中访问
Length
属性,我看不出有任何理由不将其限制为明确具有此属性的类型。

否,C没有类型擦除-只有Java有

但是如果只指定T,而没有任何约束,就不能使用obj.Lenght,因为T实际上可以是任何东西

foo(new Bar());
上述内容将解析为Bar类,因此Length属性可能不可用。 只有当您确保T上的方法也确实具有时,才能使用T上的方法。(这是通过where约束完成的。)

使用dynamics,您可以放松编译时检查,我建议您不要使用它们来破解泛型。

不,C#没有类型擦除-只有Java有

但是如果只指定T,而没有任何约束,就不能使用obj.Lenght,因为T实际上可以是任何东西

foo(new Bar());
上述内容将解析为Bar类,因此Length属性可能不可用。 只有当您确保T上的方法也确实具有时,才能使用T上的方法。(这是通过where约束完成的。)

使用dynamics,您可以放松编译时检查,我建议您不要使用它们来破解泛型。

“Dynamics是一个功能强大的新工具,它使与动态语言以及COM的互操作变得更容易,并可用于替换过于臃肿的反射代码。它们可以用来告诉编译器对对象执行操作,对对象的检查推迟到运行时

最大的危险在于在不适当的上下文中使用动态对象,例如在静态类型的系统中,或者更糟的是,在正确类型的系统中使用接口/基类。”

“Dynamics是一种功能强大的新工具,它使与动态语言以及COM的互操作变得更加简单,并可用于替换过于臃肿的反射代码。它们可以用来告诉编译器对对象执行操作,对对象的检查推迟到运行时

最大的危险在于在不适当的上下文中使用动态对象,例如在静态类型的系统中,或者更糟的是,在正确类型的系统中使用接口/基类。”

我相信这不起作用的原因是在C#和java中,是由于一个称为类型擦除的概念,请参阅

不,这不是因为类型擦除。无论如何,C#中没有类型擦除(与Java不同):运行时为每个不同的类型参数集构造不同的类型,不会丢失信息

它不起作用的原因是编译器对
t
一无所知,因此它只能假设
t
继承自
object
,因此只有
object
的成员可用。但是,您可以通过在t上添加约束向编译器提供更多信息。例如,如果您有一个interface
IBar
使用
Length
属性,可以添加如下约束:

int foo<T>(T bar) where T : IBar
{
    return bar.Length;
}
intfoo(T条),其中T:IBar
{
回程杆