찾다

C#2.0 사양(제네릭 2)

Jan 03, 2017 am 10:27 AM

20.1.6 제네릭 클래스의 정적 생성자

제네릭 클래스의 정적 생성자는 특정 제네릭 클래스 선언에서 생성된 각각의 정적 필드를 초기화하는 데 사용됩니다. 밀접하게 구성된 유형은 추가 초기화를 수행합니다. 제네릭 형식으로 선언된 형식 매개 변수는 범위 내에 있으며 정적 생성자의 본문 내에서 사용할 수 있습니다.

다음 상황 중 하나가 발생하면 새로운 폐쇄형 생성 클래스 유형이 처음으로 초기화됩니다.

폐쇄형 생성 유형의 인스턴스가 생성될 때

폐쇄형 생성 유형의 정적 멤버가 참조될 때

새로운 폐쇄형 생성 클래스 유형을 초기화하려면, 먼저 특정 둘러싸는 유형의 새로운 정적 필드 세트(§20.1.5)가 생성됩니다. 각 정적 필드는 기본값(§5.2)으로 초기화됩니다. 다음으로 이러한 정적 필드에 대해 정적 필드 이니셜라이저(§10.4.5.1)가 실행됩니다. 마지막으로 정적 생성자가 실행됩니다.

정적 생성자는 둘러싸는 생성된 클래스 유형마다 한 번씩 실행되므로 제약 조건(§20.7)으로 확인할 수 없는 유형 매개 변수에 대한 런타임 확인을 구현하는 것이 편리합니다. 예를 들어 다음 형식은 정적 생성자를 사용하여 형식 매개 변수가 참조 형식인지 확인합니다.

class Gen<T>
{
static Gen(){
if((object)T.default != null){
throw new ArgumentException(“T must be a reference type”);
}
}
}

20.1.7 보호된 멤버에 대한 액세스

일반 클래스 선언에서는 일반 클래스에서 상속된 보호된 인스턴스 멤버에 대한 액세스가 허용됩니다. 모든 유형의 인스턴스를 구성하면 문제가 해결됩니다. . 특히 §3.5.3에 지정된 protected 및 protected 내부 인스턴스 멤버에 액세스하기 위한 규칙은 다음 규칙을 사용하여 제네릭에 대해 확장됩니다.

일반 클래스 G에서 상속된 보호 인스턴스 멤버 M의 경우 E.M을 사용하는 기본 표현식이 허용됩니다. 단, E 유형은 G에서 생성된 클래스 유형이거나 A 클래스 유형에서 상속됩니다. G로 구성된 클래스 유형.



예제

class C<T>
{
protected T x;
}
class D<T> :C<T>
{
static void F(){
D<T> dt = new D<T>();
D<int> di = new D<int>();
D<string> ds = new D<string>();
dt.x = T.default;
di.x = 123;
ds.x = “test”;
}
}

에서는 x에 대한 세 가지 대입문이 모두 허용됩니다. 왜냐하면 모두 제네릭으로 구성된 클래스 유형의 인스턴스를 통해 발생하기 때문입니다.

20.1.8 일반 클래스의 오버로드

일반 클래스 선언의 메서드, 생성자, 인덱서 및 연산자는 오버로드될 수 있습니다. 그러나 생성된 클래스의 모호성을 피하기 위해 이러한 오버로드는 제한됩니다. 동일한 제네릭 클래스 선언에서 동일한 이름으로 선언된 두 함수 멤버에는 이러한 매개 변수 형식이 있어야 합니다. 즉, 동일한 이름과 시그니처를 가진 두 멤버는 폐쇄형 생성 형식에 나타날 수 없습니다. 가능한 모든 폐쇄형 생성 유형을 고려할 때 이 규칙은 현재 프로그램에 존재하지 않는 유형이 실제 매개변수일 가능성을 포괄하지만 여전히 가능합니다[1]. 이 규칙의 목적에 따라 유형 매개변수에 대한 유형 제약 조건은 무시됩니다.

다음 예는 이 규칙에 따른 유효한 오버로드와 잘못된 오버로드를 보여줍니다.

nterface I1<T> {…}
interface I2<T>{…}

class G1<U>
{
long F1(U u); //无效重载,G<int>将会有使用相同签名的两个成员
int F1(int i);
void F2(U u1, U u2); //有效重载,对于U没有类型参数
void F2(int I , string s); //可能同时是int和string 
void F3(I1<U>a); //有效重载
void F3(I2<U>a);
void F4(U a); //有效重载
void F4(U[] a);}

class G2<U,V>
{
void F5(U u , V v); //无效重载,G2<int , int>将会有两个签名相同的成员
void F5(V v, U u);
void F6(U u , I1<V> v);//无效重载,G2<I1<int>,int>将会有两个签名相同的成员
void F6(I1<V> v , U u);
void F7(U u1,I1<V> V2);//有效的重载,U不可能同时是V和I1<V>
void F7(V v1 , U u2);
void F8(ref U u); //无效重载
void F8(out V v);
}
class C1{…}
class C2{…}
class G3<U , V> where U:C1 where V:C2
{
void F9(U u); //无效重载,当检查重载时,在U和V上的约束将被忽略
void F9(V v);
}

0.1.9 매개변수 배열 방식 및 유형 매개변수

매개변수 배열 유형에는 유형 매개변수를 사용할 수 있습니다. 예를 들어

class C<V>
{
static void F(int x, int y ,params V[] args);
}
方法的扩展形式的如下调用

C<int>.F(10, 20);
C<object>.F(10,20,30,40);
C<string>.F(10,20,”hello”,”goodbye”);

对应于如下形式:

C<int>.F(10,20, new int[]{});
C<object>.F(10,20,new object[]{30,40});
C<string>.F(10,20,new string[](“hello”,”goodbye”));

20.1.10 재정의 및 일반 클래스

선언이 있다고 가정해 보겠습니다.

在泛型类中的函数成员可以重写基类中的函数成员。如果基类是一个非泛型类型或封闭构造类型,那么任何重写函数成员不能有包含类型参数的组成类型。然而,如果一个基类是一个开放构造类型,那么重写函数成员可以使用在其声明中的类型参数。当重写基类成员时,基类成员必须通过替换类型实参而被确定,如§20.5.4中所描述的。一旦基类的成员被确定,用于重写的规则和非泛型类是一样的。

下面的例子演示了对于现有的泛型其重写规则是如何工作的。

abstract class C<T>
{
public virtual T F(){…}
public virtual C<T> G(){…}
public virtual void H(C<T> x ){…}
} 
class D:C<string>
{
public override string F(){…}//OK
public override C<string> G(){…}//OK
public override void H(C<T> x); //错误,应该是C<string>
}
class E<T,U>:C<U>
{
public override U F(){…}//OK
public override C<U> G(){…}//OK
public override void H(C<T> x){…}//错误,应该是C<U>
}

20.1.11泛型类中的运算符

泛型类声明可以定义运算符,它遵循和常规类相同的规则。类声明的实例类型(§20.1.2)必须以一种类似于运算符的常规规则的方式,在运算符声明中被使用,如下

一元运算符必须接受一个实例类型的单一参数。一元运算符“++”和“—”必须返回实例类型。

至少二元运算符的参数之一必须是实例类型。

转换运算符的参数类型和返回类型都必须是实例类型。


下面展示了在泛型类中几个有效的运算符声明的例子

class X<T>
{
public static X<T> operator ++(X(T) operand){…}
public static int operator *(X<T> op1, int op2){…}
public static explicit operator X<T>(T value){…}
}

对于一个从源类型S到目标类型T的转换运算符,当应用§10.9.3中的规则时,任何关联S或T的类型参数被认为是唯一类型,它们与其他类型没有继承关系,并且在这些类型参数上的任何约束都将被忽略。

在例子

class C<T>{…}
class D<T>:C<T>
{
public static implicit operator C<int>(D<T> value){…}//OK
public static implicit operator C<T>(D<T> value){…}//错误
}

第一个运算符声明是允许的,由于§10.9.3的原因,T和int被认为是没有关系的唯一类型。然而,第二个运算符是一个错误,因为C是D的基类。

给定先前的例子,为某些类型实参声明运算符,指定已经作为预定义转换而存在的转换是可能的。

struct Nullable<T>
{
public static implicit operator Nullable<T>(T value){…}
public static explicit operator T(Nullable<T> value){…}
}

当类型object作为T的类型实参被指定,第二个运算符声明了一个已经存在的转换(从任何类型到object是一个隐式的,也可以是显式的转换)。

在两个类型之间存在预定义的转换的情形下,在这些类型上的任何用户定义的转换都将被忽略。尤其是

如果存在从类型S到类型T的预定义的隐式转换(§6.1),所有用户定义的转换(隐式的或显式的)都将被忽略。

如果存在从类型S到类型T的预定义的显式转换,那么任何用户定义的从类型S到类型T的显式转换都将被忽略。但用户定义的从S到T的隐式转换仍会被考虑。

对于所有类型除了object,由Nullable类型声明的运算符都不会与预定义的转换冲突。例如

void F(int I , Nullable<int> n){
i = n; //错误
i = (int)n; //用户定义的显式转换
n = i; //用户定义的隐式转换
n = (Nullable<int>)i; //用户定义的隐式转换
}

然而,对于类型object,预定义的转换在所有情况隐藏了用户定义转换,除了一种情况:

void F(object o , Nullable<object> n){
o = n; //预定义装箱转换
o= (object)n; //预定义装箱转换
n= o; //用户定义隐式转换
n = (Nullable<object>)o; //预定义取消装箱转换
}


20.1.12泛型类中的嵌套类型

泛型类声明可以包含嵌套类型声明。封闭类的类型参数可以在嵌套类型中使用。嵌套类型声明可以包含附加的类型参数,它只适用于该嵌套类型。

包含在泛型类声明中的每个类型声明是隐式的泛型类型声明。当编写一个嵌套在泛型类型内的类型的引用时,包含构造类型,包括它的类型实参,必须被命名。然而,在外部类中,内部类型可以被无限制的使用;当构造一个内部类型时,外部类的实例类型可以被隐式地使用。下面的例子展示了三个不同的引用从Inner创建的构造类型的方法,它们都是正确的;前两个是等价的。
class Outer<T>
{
class Inner<U>
{
static void F(T t , U u){…}
}
static void F(T t)
{
Outer<T>.Inner<string >.F(t,”abc”);//这两个语句有同样的效果
Inner<string>.F(t,”abc”);
Outer<int>.Inner<string>.F(3,”abc”); //这个类型是不同的
Outer.Inner<string>.F(t , “abc”); //错误,Outer需要类型参数
}
}

尽管这是一种不好的编程风格,但嵌套类型中的类型参数可以隐藏一个成员,或在外部类型中声明的一个类型参数。

class Outer<T>
{
class Inner<T> //有效,隐藏了 Ouer的 T
{
public T t; //引用Inner的T
}
}

20.1.13应用程序入口点

应用程序入口点不能在一个泛型类声明中。

20.2泛型结构声明

像类声明一样,结构声明可以有可选的类型参数。

struct-declaration:(结构声明:)
attributes opt struct-modifiers opt struct identifier type-parameter-list opt struct-interfaces opt type-parameter-constraints-clauses opt struct-body ;opt
(特性可选 结构修饰符可选 struct 标识符 类型参数列表可选 结构接口可选 类型参数约束语句可选 结构体;可选)

除了§11.3中为结构声明而指出的差别之外,泛型类声明的规则也适用于泛型结构声明。

20.3泛型接口声明

接口也可以定义可选的类型参数

interface-declaration:(接口声明:)
attribute opt interface-modifiers opt interface indentifier type-parameter-list opt 
interface-base opt type-parameter-constraints-clause opt interface-body;
(特性可选 接口修饰符可选 interface 标识符 类型参数列表可选 基接口可选 类型参数约束语句可选 接口体;可选)
使用类型参数声明的接口是一个泛型接口声明。除了所指出的那些,泛型接口声明遵循和常规结构声明相同的规则。

在接口声明中的每个类型参数在接口的声明空间定义了一个名字。在一个接口上的类型参数的作用域包括基接口、类型约束语句和接口体。在其作用域之内,一个类型参数可以被用作一个类型。应用到接口上的类型参数和应用到类(§20.1.1)上的类型参数具有相同的限制。

在泛型接口中的方法与泛型类(§20.1.8)中的方法遵循相同的重载规则。

20.3.1实现接口的唯一性

由泛型类型声明实现的接口必须为所有可能的构造类型保留唯一性。没有这条规则,将不可能为特定的构造类型确定调用正确的方法。例如,假定一个泛型类声明允许如下写法。

interface I<T>
{
void F();
}
class X<U, V>:I<U>,I<V> //错误,I<U>和I<V>冲突
{
void I<U>.F(){…}
void I<V>.F(){…}
}

如果允许这么写,那么下面的情形将无法确定执行那段代码。

I<int> x = new X<int ,int>();
x.F();

为了确定一个泛型类型声明的接口列表是有效的,可以按下面的步骤进行。

让L成为在泛型类、结构或接口声明 C中指定的接口的列表。

将任何已经在L中的接口的基接口添加到L

从L中删除任何重复的接口

在类型实参被替换到L后,如果任何从C创建的可能构造类型,导致在L中的两个接口是同一的,那么C的声明是无效的。当确定所有可能的构造类型时,约束声明不予考虑。


在类声明X之上,接口列表L由I和I组成。该声明是无效的,因为任何使用相同类型U和V的构造类型,将导致这两个接口是同一的。

20.3.2显式接口成员实现

使用构造接口类型的显式接口成员实现本质上与简单接口类型方式上是相同的。和以往一样,显式接口成员实现必须由一个指明哪个接口被实现的接口类型而限定。该类型可能是一个简单接口或构造接口,如下例子所示。

interface IList<T>
{
T[] GetElement();
}
interface IDictionary<K,V>
{
V this[K key];
Void Add(K key , V value);
}
class List<T>:IList<T>,IDictionary<int , T>
{
T[] IList<T>.GetElement(){…}
T IDictionary<int , T>.this[int index]{…}
void IDictionary<int , T>.Add(int index , T value){…}
}

[1] 也就是在类型参数被替换成类型实参时,有可能替换后的实参导致出现两个成员使用相同的名字和签名。


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

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
C# .NET : 핵심 개념 탐색 및 프로그래밍 기초C# .NET : 핵심 개념 탐색 및 프로그래밍 기초Apr 10, 2025 am 09:32 AM

C#은 Microsoft가 개발 한 최신 객체 지향 프로그래밍 언어이며 .NET 프레임 워크의 일부로 개발되었습니다. 1.C#은 캡슐화, 상속 및 다형성을 포함한 객체 지향 프로그래밍 (OOP)을 지원합니다. 2. C#의 비동기 프로그래밍은 응용 프로그램 응답 성을 향상시키기 위해 비동기 및 키워드를 기다리는 키워드를 통해 구현됩니다. 3. LINQ를 사용하여 데이터 컬렉션을 간결하게 처리하십시오. 4. 일반적인 오류에는 NULL 참조 예외 및 인덱스 외 예외가 포함됩니다. 디버깅 기술에는 디버거 사용 및 예외 처리가 포함됩니다. 5. 성능 최적화에는 StringBuilder 사용 및 불필요한 포장 및 Unboxing을 피하는 것이 포함됩니다.

C# .NET 응용 프로그램 테스트 : 장치, 통합 및 엔드 투 엔드 테스트C# .NET 응용 프로그램 테스트 : 장치, 통합 및 엔드 투 엔드 테스트Apr 09, 2025 am 12:04 AM

C#.NET 애플리케이션에 대한 테스트 전략에는 단위 테스트, 통합 테스트 및 엔드 투 엔드 테스트가 포함됩니다. 1. 단위 테스트를 통해 MSTEST, NUNIT 또는 XUNIT 프레임 워크를 사용하여 코드의 최소 단위가 독립적으로 작동합니다. 2. 통합 테스트는 일반적으로 사용되는 시뮬레이션 된 데이터 및 외부 서비스를 결합한 여러 장치의 기능을 확인합니다. 3. 엔드 투 엔드 테스트는 사용자의 완전한 작동 프로세스를 시뮬레이션하며 셀레늄은 일반적으로 자동 테스트에 사용됩니다.

Advanced C# .NET 튜토리얼 : ACE 귀하의 다음 선임 개발자 인터뷰Advanced C# .NET 튜토리얼 : ACE 귀하의 다음 선임 개발자 인터뷰Apr 08, 2025 am 12:06 AM

C# 수석 개발자와의 인터뷰에는 비동기 프로그래밍, LINQ 및 .NET 프레임 워크의 내부 작업 원리와 같은 핵심 지식을 마스터하는 것이 필요합니다. 1. 비동기 프로그래밍은 비동기를 통해 작업을 단순화하고 응용 프로그램 응답 성을 향상시키기 위해 기다리고 있습니다. 2.linq는 SQL 스타일로 데이터를 운영하고 성능에주의를 기울입니다. 3. Net Framework의 CLR은 메모리를 관리하며 가비지 컬렉션은주의해서 사용해야합니다.

C# .NET 인터뷰 질문 및 답변 : 전문 지식 레벨 업C# .NET 인터뷰 질문 및 답변 : 전문 지식 레벨 업Apr 07, 2025 am 12:01 AM

C#.NET 인터뷰 질문 및 답변에는 기본 지식, 핵심 개념 및 고급 사용이 포함됩니다. 1) 기본 지식 : C#은 Microsoft가 개발 한 객체 지향 언어이며 주로 .NET 프레임 워크에 사용됩니다. 2) 핵심 개념 : 위임 및 이벤트는 동적 바인딩 방법을 허용하고 LINQ는 강력한 쿼리 기능을 제공합니다. 3) 고급 사용 : 비동기 프로그래밍은 응답 성을 향상시키고 표현 트리는 동적 코드 구성에 사용됩니다.

C# .NET을 사용하여 마이크로 서비스 구축 : 건축가를위한 실용 가이드C# .NET을 사용하여 마이크로 서비스 구축 : 건축가를위한 실용 가이드Apr 06, 2025 am 12:08 AM

C#.net은 강력한 생태계와 풍부한 지원으로 인해 마이크로 서비스를 구축하는 데 인기있는 선택입니다. 1) ASP.NETCORE를 사용하여 RESTFULAPI를 작성하여 주문 생성 및 쿼리를 처리하십시오. 2) GRPC를 사용하여 마이크로 서비스 간의 효율적인 통신을 달성하고 주문 서비스를 정의하고 구현하십시오. 3) Docker Containerized 마이크로 서비스를 통해 배포 및 관리를 단순화합니다.

C# .NET 보안 모범 사례 : 일반적인 취약점 방지C# .NET 보안 모범 사례 : 일반적인 취약점 방지Apr 05, 2025 am 12:01 AM

C# 및 .NET의 보안 모범 사례에는 입력 확인, 출력 인코딩, 예외 처리, 인증 및 인증이 포함됩니다. 1) 일반 표현식 또는 내장 방법을 사용하여 악성 데이터가 시스템에 들어가는 것을 방지하기 위해 입력을 확인하십시오. 2) XSS 공격을 방지하기 위해 출력 인코딩 httputility.htmlencode 메서드를 사용하십시오. 3) 예외 처리는 정보 유출을 피하고 오류를 기록하지만 자세한 정보를 사용자에게 반환하지는 않습니다. 4) ASP.NETIDENITY 및 CAMPLES 기반 승인을 사용하여 신청서를 무단 액세스로부터 보호합니다.

C 언어 : 무엇을 의미 하는가C 언어 : 무엇을 의미 하는가Apr 03, 2025 pm 07:24 PM

C 언어의 결장의 의미 ( ':') : 조건부 명세서 : 조건부 표현 및 명령문 분리 블록 루프 문 : 초기화, 조건부 및 증분 표현식 매크로 정의 분리 : 매크로 이름 및 매크로 값 단일 라인 주석 설명 : 콜론에서 라인으로의 내용을 주석 차원으로 표현

C 언어에서 무엇을 의미 하는가C 언어에서 무엇을 의미 하는가Apr 03, 2025 pm 07:21 PM

A In Canue in-Conecrease Operator이며 운영 메커니즘에는 다음이 포함됩니다. 먼저 변수 값을 얻습니다. a. A의 값을 1 x 1. 증가 후 A의 값을 반환합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음