>  기사  >  백엔드 개발  >  C#2.0 사양(제네릭 1)

C#2.0 사양(제네릭 1)

黄舟
黄舟원래의
2017-01-03 10:22:211149검색

이 장은 너무 길기 때문에 여러 부분으로 나누어야 할 수도 있습니다 :)

20. 제네릭

20.1 제네릭 클래스 선언

제네릭 클래스 선언은 실제 유형을 형성하기 위해 유형 매개변수가 필요한 클래스 선언입니다.



클래스 선언에서는 선택적으로 유형 매개변수를 정의할 수 있습니다.

클래스 선언: (클래스 선언)
attributesopt class-modifiersopt 클래스 식별자opt type-parameter-listopt class –baseopt type-parameter-constraints-clauseopt class-body;opt(속성 선택적 클래스 수정자 선택적 클래스 식별자 선택적 유형 매개변수 목록 선택적 기본 클래스 선택적 유형 매개변수 제한문 선택적 클래스 본문 선택)
유형 매개변수 목록이 제공되지 않는 한 클래스 선언은 유형 매개변수화된 제약문을 제공할 필요가 없습니다.

유형 매개변수 목록을 제공하는 클래스 선언은 일반 클래스 선언입니다. 또한 생성된 유형을 생성하려면 포함하는 유형의 유형 매개변수를 제공해야 하기 때문에 제네릭 클래스 선언 또는 제네릭 구조체 선언에 포함된 모든 클래스는 그 자체로 제네릭 클래스 선언입니다.

제네릭 유형 클래스는 생성된 클래스를 사용하여 참조됩니다. 유형(§20.5). 일반 클래스 선언

class List{}
다음은 생성된 유형, List, List 및 List>의 몇 가지 예입니다. 생성된 유형은 하나 이상의 매개변수를 사용할 수 있습니다. 예를 들어 List를 개방형 생성 유형이라고 합니다. List와 같은 유형 매개변수를 사용하지 않는 생성된 유형을 폐쇄형 생성 유형이라고 합니다.

일반 유형은 "오버로드"될 수 없습니다. 즉, 일반 유형과 마찬가지로 범위 내에서 고유하게 이름이 지정되어야 합니다.


클래스 C{}
클래스 Cd94943c0b4933ad8cac500132f64757f{}//오류, C가 두 번 정의되었습니다.
클래스 Cf3887e50b478d7d3734323cd28ecc8ff{}//오류, C가 정의되었습니다.
그러나 정규화되지 않은 유형 이름 조회(§20.9.3) 및 멤버 액세스(§20.9.4)에 사용되는 유형 조회 규칙은 유형 매개변수 수를 고려합니다.

20.1.1 유형 매개변수

유형 매개변수는 클래스 선언에 제공될 수 있습니다. 각 유형 매개변수는 생성된 유형을 생성하는 데 사용되는 유형 매개변수에 대한 자리 표시자를 나타내는 단순 식별자입니다. 유형 매개변수는 나중에 제공될 유형에 대한 공식적인 자리 표시자입니다. 대조적으로, 유형 매개변수 §20.5.1)은 생성된 유형이 참조될 때 실제 유형에 대한 단순한 프록시입니다.

type-parameter-list: (유형 매개변수 목록:)
8ca0a478262839a5decb26c938e12c8f 유형-매개변수(유형 매개변수)
유형 매개변수 유형-매개변수(유형 매개변수, 유형 매개변수)
type-parameter: (유형 매개변수:)
attributesopt 식별자(속성 선택적 식별자) ​​

클래스 선언의 각 유형 매개변수는 클래스 선언 공간(§3.3)에 이름을 정의합니다. 따라서 클래스에 선언된 다른 형식 매개 변수나 멤버와 동일한 이름을 가질 수 없습니다. 유형 매개변수는 유형 자체와 동일한 이름을 가질 수 없습니다.

기본 클래스, 유형 매개변수 제약 조건문 및 클래스 본문을 포함한 클래스(§3.7)의 유형 매개변수 범위입니다. 클래스의 멤버와 달리 파생 클래스로 확장되지 않습니다. 해당 범위 내에서 유형 매개변수를 유형으로 사용할 수 있습니다.

유형:

value-type(값 유형)
reference-type(참조 유형)
type-parameter(유형 매개변수)
유형 매개변수로 인해 가능 다른 유형과 약간 다른 작업 및 제한 사항이 있는 다양한 실제 유형 인수로 인스턴스화됩니다. 다음이 포함됩니다.

유형 매개변수는 기본 유형이나 인터페이스를 직접 선언하는 데 사용할 수 없습니다.
유형 매개변수에 대한 멤버 조회 규칙의 경우 제약조건이 있으면 유형 매개변수에 적용되는 제약조건에 따라 달라집니다. 자세한 설명은 §20.7.4를 참조하세요.



유형 매개변수에 가능한 변환은 유형 매개변수에 적용된 제약조건(있는 경우)에 따라 다릅니다. 자세한 내용은 §20.7.4를 참조하세요.
유형 매개변수가 클래스 제약 조건(§20.7.4)에 의해 제한되지 않는 한 리터럴 null은 유형 매개변수에 의해 지정된 유형으로 변환될 수 없습니다. 그러나 기본값 표현식(§20.8.1)을 대신 사용할 수 있습니다. 추가적으로, 유형 매개변수에 의해 주어진 유형의 값은 "==" 및 "!="를 사용하여 null과 비교될 수 ​​있습니다(§20.8.4).
유형 매개변수가 생성자 제약 조건(§20.7)으로 제한되는 경우 새 표현식은 하나의 유형 매개변수에만 사용할 수 있습니다.
유형 매개변수는 속성 내 어디에서나 사용할 수 없습니다.
유형 매개변수는 멤버 액세스에 사용할 수 없으며 정적 멤버 또는 중첩 유형의 유형 이름을 나타낼 수 없습니다(§20.9.1, §20.9.4).
안전하지 않은 코드에서는 유형 매개변수를 관리 유형으로 사용할 수 없습니다(§18.2).

유형으로서 유형 매개변수는 순전히 컴파일 타임 구성입니다. 런타임 시 각 유형 매개변수는 제네릭 유형 선언에서 제공하는 유형 인수에 의해 지정되는 런타임 유형에 바인딩됩니다. 이러한 이유로 런타임 시 유형 매개변수로 선언된 변수의 유형은 폐쇄형 유형입니다(§20.5.2). 런타임에 실행되는 모든 문과 표현식은 해당 매개변수에서 제공하는 실제 유형의 유형 매개변수를 유형 인수로 사용합니다.



20.1.2 인스턴스 유형

각 클래스 선언에는 이와 관련된 생성된 유형, 즉 인스턴스 유형이 있습니다. 제네릭 클래스 선언의 경우 인스턴스 유형은 유형 매개 변수에 해당하는 각 유형 인수를 사용하는 유형 선언에서 생성된 유형(§20.4)을 생성하여 구성됩니다. 인스턴스화된 유형은 유형 매개변수를 사용하기 때문에 유형 매개변수 범위(클래스 선언 내)에서만 유효합니다. 인스턴스 유형은 클래스 선언에 있는 this 유형입니다. 제네릭이 아닌 클래스의 경우 인스턴스 유형은 선언된 유형일 뿐입니다. 아래에는 인스턴스 유형과 함께 선언된 여러 클래스가 나와 있습니다.


20.1.3 기본 클래스 사양
class A<T> //实例类型:A<T>
{
class B{} //实例类型:A<T>.B
class C<U>{} //实例类型:A<T>.C<U>
}
class D{} //实例类型:D

클래스 선언에 지정된 기본 클래스는 생성된 형식일 수 있습니다(§20.5). 기본 클래스 자체는 유형 매개변수가 될 수 없지만 해당 범위 내에 유형 매개변수를 포함할 수 있습니다.


class Extendd94943c0b4933ad8cac500132f64757f: V{}//오류, 유형 매개변수가 기본 클래스로 사용됩니다.
일반 클래스 선언에서는 System.Attribute를 직접 또는 간접 기본 클래스로 사용할 수 없습니다.

클래스 선언에 지정된 기본 인터페이스는 생성된 인터페이스 유형일 수 있습니다(§20.5). 기본 인터페이스 자체는 유형 매개변수가 될 수 없지만 해당 범위 내에 유형 매개변수를 포함할 수 있습니다. 다음 코드는 생성된 유형을 구현하고 확장하는 방법을 보여줍니다.



제네릭 형식으로 선언된 기본 인터페이스는 §20.3.1에 설명된 고유성 규칙을 충족해야 합니다.
class C<U,V>{}
Interface I1<V>{}
class D:C<string , int>,I1<string>{}
class E<T>:C<int,T> ,I1<T>{}

기본 클래스나 인터페이스의 메서드를 재정의하거나 구현하는 클래스의 메서드는 특정 유형에 적합한 메서드를 제공해야 합니다. 아래 코드는 메서드를 재정의하고 구현하는 방법을 보여줍니다. 이에 대해서는 §20.1.10에서 자세히 설명합니다.



20.1.4 일반 클래스 멤버
class C<U,V>
{
public virtual void M1(U x , List<V> y){…}
}
interface I1<V>
{
V M2(V x);
}
class D:C<string , int>,I1<string>
{
public override void M1(string x , List<int> y){…}
public string M2(string x){…}
}

泛型类的所有成员都可以直接地或者作为构造类型的一部分,从任何封闭类(enclosing class)中使用类型参数。当特定的封闭构造类型在运行时被使用时,类型参数的每次使用都由构造类型所提供的实际类型实参所代替。例如


class C<V>
{ 
public V f1; 
public C<V> f2=null;
public C(V x){
this.f1 = x;
this.f2 = this;
}
}
class Application
{
static void Main(){
C<int> x1= new C<int >(1);
Console.WriteLine(x1.f1); //打印1
C<double> x2 = new C<double>(3.1415);
Console.WriteLine(x2.f1); //打印 3.1415
}
}

在实例函数成员之内,this的类型就是声明的实例类型(§20.1.2)。

除了使用类型参数作为类型和成员,在泛型类声明中也遵循和非泛型类成员相同的规则。适用于特定种类成员的附加规则将在后面几节进行讨论。

20.1.5泛型类中的静态字段

在一个泛型类声明中的静态变量,在相同封闭构造类型(§20.5.2)所有实例中被共享,但在不同封闭构造类型的实例中[1],是不被共享的。这些规则不管静态变量的类型包含那种类型参数都适用。

例如

class C<V>
{
static int count = 0;
public C()
{
count++;
}
public static int Count{
get{return count;}
}
}
class Application
{
static void Main()
{
C<int> x1 = new C<int>();
Console.WriteLine(C<int>.Count);//打印 1
C<double> x2 = new C<double>();
Console.WriteLine(C<int>.Count);//打印 1
C<int> x3 = new C<int>();
Console.WriteLine(C<int>.Count);//打印 2
}
}

[1] 这是很容易理解的,因为在运行时,不同的封闭构造类型,是属于不同的类型,比如Listbd43222e33876353aff11e13a7dc75f6 和List98c455a79ddfebb79781bff588e7b37e 这二者的实例是不能共享静态变量的。

以上就是C#2.0 Specification(泛型一)的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:C# 2.0 사양(4)다음 기사:C# 2.0 사양(4)