C# .NET 中的“开放泛型类型”究竟是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2173107/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:07:28  来源:igfitidea点击:

What exactly is an "open generic type" in .NET?

c#.netgenericsopen-generics

提问by Asad

I was going through Asp.Net MVC lessonand learned that, for a method to qualify as an action for a controller,

我正在学习Asp.Net MVC 课程并了解到,对于有资格作为控制器操作的方法,

  • It must not have an "open generic type"
  • 它不能有“开放泛型类型”

I understand generics somewhat and use them to some extent, but:

我有点理解泛型并在某种程度上使用它们,但是:

  • What is an open generic typein .Net.
  • Is there such a thing as a closed generic type?
  • Open generic typeis a term not used very often. What is used / confused with it ?
  • 什么是.Net 中的开放泛型类型
  • 是否有封闭泛型类型之类的东西?
  • 开放泛型是一个不常用的术语。有什么用/与之混淆?

采纳答案by Mehrdad Afshari

The C# language defines an open type to be a type that's either a type argument or a generic type defined with unknown type arguments:

C# 语言将开放类型定义为类型参数或使用未知类型参数定义的泛型类型:

All types can be classified as either open types or closed types. An open typeis a type that involves type parameters. More specifically:

  • A type parameter defines an open type.
  • An array type is an open type if and only if its element type is an open type.
  • A constructed typeis an open type if and only if one or more of its type arguments is an open type. A constructed nested typeis an open type if and only if one or more of its type arguments or the type arguments of its containing type(s) is an open type.

A closed typeis a type that is not an open type.

所有类型都可以分为开放类型或封闭类型。一个开放式的,涉及类型参数的类型。进一步来说:

  • 类型参数定义开放类型。
  • 数组类型是开放类型当且仅当其元素类型是开放类型。
  • 构造类型是开放型,当且仅当其类型参数中的一个或多个是一个开放型。甲构造嵌套类型是开放型,当且仅当一个或多个其类型参数或包含它的类型的类型参数是一个开放型。

一个封闭式是一种类型,是不是开放类型。

Therefore T, List<T>, and Dictionary<string,T>, and Dictionary<T,U>are all open types (Tand Uare type arguments) whereas List<int>and Dictionary<string,int>are closed types.

因此T, List<T>, 和Dictionary<string,T>, andDictionary<T,U>都是开放类型(T并且U是类型参数),而List<int>Dictionary<string,int>是封闭类型。

There's a related concept: An unbound generic typeis a generic type with unspecified type arguments. An unbound type can't be used in expressions other than typeof()and you can't instantiate it or call its methods. For instance, List<>and Dictionary<,>are unbound types.

有一个相关的概念:未绑定泛型类型是具有未指定类型参数的泛型类型。未绑定类型不能在表达式中使用,typeof()并且您不能实例化它或调用它的方法。例如,List<>Dictionary<,>是未绑定的类型。

To clarify the subtle distinction between an open type and an unbound type:

澄清开放类型和未绑定类型之间的细微区别:

class Program {
   static void Main() { Test<int>(); }
   static void Test<T>() {
      Console.WriteLine(typeof(List<T>)); // Print out the type name
   }
}

If you run this snippet, it'll print out

如果你运行这个片段,它会打印出来

System.Collections.Generic.List`1[System.Int32]

which is the CLR name for List<int>. It's clear at runtime that the type argument is System.Int32. This makes List<T>a boundopen type.

这是List<int>. 在运行时很清楚类型参数是System.Int32. 这使得List<T>一个边界开放式。

At runtime, you can use reflection to bind type arguments to unspecified type parameters of unbound generic types with the Type.MakeGenericTypemethod:

在运行时,您可以使用反射将类型参数绑定到未绑定泛型类型的未指定类型参数,Type.MakeGenericType方法如下:

Type unboundGenericList = typeof(List<>);
Type listOfInt = unboundGenericList.MakeGenericType(typeof(int));
if (listOfInt == typeof(List<int>))
     Console.WriteLine("Constructed a List<int> type.");

You can check whether a type is an unbound generic type (generic type definition) from which you can construct bound types with the Type.IsGenericTypeDefinitionproperty:

您可以检查类型是否是未绑定的泛型类型(泛型类型定义),您可以从中构造具有Type.IsGenericTypeDefinition属性的绑定类型:

Console.WriteLine(typeof(Dictionary<,>).IsGenericTypeDefinition); // True
Console.WriteLine(typeof(Dictionary<int,int>).IsGenericTypeDefinition); // False

To get the unbound type from a constructed type at runtime, you can use the Type.GetGenericTypeDefinitionmethod.

要在运行时从构造类型获取未绑定类型,可以使用Type.GetGenericTypeDefinition方法

Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)

Note that for a generic type, you can either have a completely unbound type definition, or a completely bound definition. You can't bind some type parameters and leave others unbound. For instance, you can't have Dictionary<int,>or Dictionary<,string>.

请注意,对于泛型类型,您可以拥有完全未绑定的类型定义或完全绑定的定义。您不能绑定某些类型参数而让其他类型参数未绑定。例如,您不能有Dictionary<int,>Dictionary<,string>

回答by John Feminella

An "open generic type" is just a generic type that doesn't yet have its type specified (e.g., CargoCrate<T>). It becomes "closed" once a concrete type has been assigned (e.g. CargoCrate<Widget>).

“开放泛型类型”只是尚未指定其类型的泛型类型(例如,CargoCrate<T>)。一旦指定了具体类型(例如CargoCrate<Widget>),它就会“关闭” 。

For example, say you have something like this:

例如,假设您有这样的事情:

public class Basket<T> {
  T[] basketItems;
}

public class PicnicBlanket<T> {
  Basket<T> picnicBasket;   // Open type here. We don't know what T is.
}

                                 // Closed type here: T is Food.
public class ParkPicnicBlanket : PicnicBlanket<Food> {
}

Here, picnicBasket's type is open: nothing's yet been assigned to T. When you make a concrete PicnicBlanket with a specific type -- for example, by writing PicnicBlanket<Food> p = new PicnicBlanket<Food>()-- we now call it closed.

在这里,picnicBasket的类型是开放的:还没有分配给T。当您制作具有特定类型的具体 PicnicBlanket 时——例如,通过书写PicnicBlanket<Food> p = new PicnicBlanket<Food>()——我们现在称其为closed

回答by leppie

Just to add:

补充一下:

Dictionary<string, T>(or more precisely Dictionary<string,>) is still an open type.

Dictionary<string, T>(或更准确地说Dictionary<string,>)仍然是开放类型。

Example:

例子:

void Foo<T>(Dictionary<string,T> dic) { ... }

回答by Gorpik

There are three kinds of generic types. To make it short, in this (simplified) declaration:

共有三种泛型类型。简而言之,在这个(简化的)声明中:

public class Dictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
  • Dictionary<TKey, TValue>is an unbounded generic type.

  • KeyValuePair<TKey, TValue>is, in this case, an open constructed generic type. It has some type parameters, but they are already defined elsewhere (in Dictionary, in this case).

  • Dictionary<string, int>would be a closed constructed generic type.

  • Dictionary<TKey, TValue>无界泛型类型

  • KeyValuePair<TKey, TValue>在这种情况下,是一个开放构造的泛型类型。它有一些类型参数,但它们已经在别处定义(在本例中是在 Dictionary 中)。

  • Dictionary<string, int>将是封闭构造的泛型类型