![](/img/trans.png)
[英]How do I use a generic class without specifying its type parameters in C#?
[英]How to use the `dynamic` when specifying generic type arguments in C#?
在 C# 中指定泛型类型参数时如何使用dynamic
?
我正在通过 C#书籍阅读CLR 。 我遇到了以下段落:
在为泛型类(引用类型)、结构(值类型)、接口、委托或方法指定泛型类型参数时,也可以使用动态。 执行此操作时,编译器会将动态转换为对象,并将 DynamicAttribute 应用于有意义的各种元数据。 请注意,您正在使用的通用代码已经过编译,并且会将类型视为 Object; 不会执行动态分派,因为编译器没有在通用代码中生成任何有效负载代码。
据我了解,这段摘录告诉我可以在(例如)类定义中使用dynamic
作为类型参数。 但是在尝试了这个之后,我得出一个结论,它与在类型参数中使用任何其他占位符没有什么不同。 所以,我怀疑我的理解是正确的。
using System;
namespace myprogram
{
class A<dynamic> {
public dynamic a;
}
class B {
public Int32 b;
}
class C<T> {
public T c;
}
class Program {
static void Main(string[] args) {
//Cannot implicitly convert type 'string' to 'myprogram.B' [Console.NET]csharp(CS0029)
//A<B> a = new A<B> {a = "foo"};
//Cannot implicitly convert type 'string' to 'myprogram.B' [Console.NET]csharp(CS0029)
//C<B> c = new C<B> {c = "foo"};
//as you can see it does not matter if I use the T or dynamic, the effect is the same
//so, what is the use of using the dynamic in the class definition?
}
}
}
理解类型“参数”和类型“参数”之间的区别非常重要。
考虑一下:
class Foo<T> { } // "T" is a type parameter
...
Foo<int> f; // "int" is a type argument
类型参数声明可以传递给这个泛型类型/方法的类型。 类型参数本质上是标识符,而不是现有类型。 当您将类型传递给泛型类型/方法时,您传递的类型称为类型参数。 这与方法参数和实参之间的区别非常相似。
所以摘录试图说给定一个泛型类型,你可以将类型dynamic
传递给它,它会被 CLR 视为object
。 这并不意味着您可以这样做:
class A<dynamic> {
}
这意味着你可以这样做:
var list = new List<dynamic>();
或者使用代码中声明的类型:
C<dynamic> c = new C<dynamic> {c = "foo"};
简短回答:在您的代码中, dynamic
只是一个类型参数名称,您实际上并没有传递参数。
据我了解,这段摘录告诉我可以在(例如)类定义中使用 dynamic 作为类型参数。
类定义中没有类型参数。 在泛型类型的定义中有类型参数。 当您构造泛型类型时,这些是类型参数。 所以这:
class A<dynamic>
{
}
var a = new A<string>();
是具有一个名称为dynamic
类型参数的泛型类型。 然后是类型的实例化,其中string
作为类型参数传递给类型参数dynamic
。 这个:
class A<T>
{
}
var a = new A<dynamic>();
是具有一个名称为T
类型参数的泛型类型。 然后是类型的实例化,其中dynamic
作为类型参数传递给类型参数T
。
您正在寻找后者,而不是前者。
您可以使用动态作为参数,因此您可以使用
var c = new C<dynamic>();
但是您不能使用具体类型来构建通用类型,例如
class A<dynamic> { }
class B<int> { }
下划线:你不应该这样做! 您正在此处定义参数名称!
实际上它不会导致编译错误,但是“int”一词被视为参数名称,与 T 相同。使用以 T 开头的名称作为泛型类型参数是一个很好的范例,而不是将其混淆,使用程序其余部分中的任何类型。
正如您自己总结的那样,您对 A 和 C 的定义完全相同,只是您感到困惑,因为这里的动态一词与类型 dynamic 无关。
如果要分配字符串,当然必须创建一个new C<string>()
或new C<object>()
或任何其他接受字符串的类型。
在我的例子中,我实际上是将 ExpandoObject 屏蔽为动态的,所以我最终使用了这样的代码:
static async Task<TReturn> GenericMethodAsync<TReturn()
{
if (typeof(TReturn) == typeof(ExpandoObject))
// Return an ExpandoObject
}
然后被这样的方法使用
static async Task<dynamic> OtherMethodAsync()
{
return await GenericMethodAsync<ExpandoObject>();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.