백엔드 개발 C#.Net 튜토리얼 C# 2.0 사양(제네릭 3)

C# 2.0 사양(제네릭 3)

Jan 03, 2017 am 10:32 AM

제네릭 2에서 계속

20.4 일반 대리자 선언

대리자 선언에는 유형 매개변수가 포함될 수 있습니다.

대리자 선언:
속성 opt 대리자 수정자 op t 대리자 반환 유형 식별자 유형 매개변수 목록 선택
(공식 매개변수 목록 선택) 유형 매개변수 제약 조건-절 선택 ;
(대리자 선언: 속성 선택적 대리자 수정자 선택적 대리자 반환 유형 식별자 유형 매개변수 목록 선택적(형식 매개변수 목록 선택적) 유형 매개변수 제약 조건문 선택적
유형 매개변수를 사용하여 선언된 대리자는 일반 대리자 선언입니다. 대리자 선언 형식 매개 변수 목록을 지원하는 경우에만 형식 매개 변수 제약 조건 문(§20.7)을 지원할 수 있습니다. 명시된 경우를 제외하고 일반 대리자 선언은 일반 대리자 선언과 동일한 규칙을 따릅니다. (§3.3) 대리자 선언의 형식 매개 변수 범위에는 반환 형식, 형식 매개 변수 목록 및 형식 매개 변수 제약 조건 문이 포함됩니다.

다른 일반 형식 선언과 마찬가지로 형식 인수도 있습니다. 생성된 대리자 형식을 형성하려면 생성된 대리자 형식의 매개 변수 및 반환 값이 대리자 선언의 생성된 대리자 형식의 각 형식 매개 변수에 해당하는 실제 매개 변수로 대체됩니다. 생성된 대리자 유형과 호환되는 메서드를 결정하는 데 사용됩니다. 예를 들어

delegate bool Predicate<T>(T value)
class X
{
static bool F(int i){…}
static bool G(string s){…}
static void Main(){
Predicate<int> p1 = F;
Predicate<string> p2=G;
}
}
로그인 후 복사

이전 Main 메서드의 두 할당은 아래의 더 긴 형식과 동일합니다. .

static void Main(){
Predicate<int> p1 = new Predicate<int>(F);
Predicate<string> p2 = new Predicate<string>(G);
}
로그인 후 복사

§21.9에 설명된 메소드 그룹 변환으로 인해 더 짧은 형식도 가능합니다. 🎜>20.5 생성된 유형

일반 유형 선언 그 자체로는 유형을 나타내지 않습니다. 대신 일반 유형 선언은 유형 인수를 적용하여 다양한 유형을 형성하기 위한 "청사진"으로 사용되며 at로 명명된 유형입니다. 최소한 하나의 인수를 생성된 유형이라고 합니다. 생성된 유형은 언어에 유형 이름이 나타날 수 있는 모든 곳에서 사용할 수 있습니다.



구성된 유형은 표현식에서도 사용할 수 있습니다. 간단한 이름(§20.9.3) 또는 멤버에 액세스(§20.9.4) >

네임스페이스 또는 유형 이름을 평가할 때 올바른 수의 유형 매개변수가 있는 일반 유형만 고려됩니다. 유형이 다른 수의 유형 매개변수를 갖고 다른 네임스페이스에서 선언되는 한, 동일한 식별자를 사용하여 다른 유형을 식별할 수 있습니다. 이는 동일한 프로그램에서 일반 클래스와 일반 클래스가 아닌 클래스를 혼합하는 데 유용합니다. 코드의 이름 조회에 대한 자세한 규칙은 §20.9에 설명되어 있습니다. 이 코드의 모호함을 해결하는 방법은 §20.6.5에 설명되어 있습니다.
type-name:(类型名字:)
namespace-or-type-name(命名空间或类型名字)
namespace-or-type-name:(命名空间或类型名字:)
identifier type-argument-list(标识符类型实参列表可选)
namespace-or-type-name. identifier(命名空间或类型名字.标识符)
type-argument-list opt(类型实参列表可选)
로그인 후 복사

유형 이름은 유형 매개변수를 직접 지정하지 않더라도 생성된 유형을 식별할 수 있습니다. 이 상황은 유형이 일반 클래스 선언 내에 중첩되어 있고 선언이 포함된 인스턴스 유형이 이름 조회(§20.1.2)로 인해 암시적으로 사용될 때 발생합니다.



생성된 유형은 안전하지 않은 코드(§18.2)에서 관리되지 않는 유형으로 사용할 수 없습니다.
namespace System.Collections
{
class Queue{…}
}
namespace Sysetm.Collections.Generic
{
class Queue<ElementType>{…}
}
namespace MyApplication
{
using System.Collections;
using System.Collections.Generic;
class X
{
Queue q1; //System.Collections.Queue
Queue<int> q2;//System.Collections.Generic.Queue
}
}
로그인 후 복사


20.5.1 유형 인수

유형 매개변수 목록의 각 실제 매개변수는 단지 유형일 뿐입니다.

class Outer<T>
{
public class Inner{…}
public Inner i; //i的类型是Outer<T>.Inner
}
로그인 후 복사


유형 인수는 생성된 유형이나 유형 매개변수가 될 수 있습니다. 안전하지 않은 코드(§18)에서는 형식 인수가 포인터 형식일 수 없습니다. 각 유형 인수는 해당 유형 매개변수(§20.7.1)에 대한 제약 조건을 준수해야 합니다.

20.5.2开放和封闭类型

所有类型都可以被分为开放类型(open type)或封闭类型(closed type)。开放类型是包含类型参数的类型。更明确的说法是

类型参数定义了一个开放类型

数组类型只有当其元素是一个开放类型时才是开放类型

构造类型只有当其类型实参中的一个或多个是开放类型时,它才是开放类型


非开放类型都是封闭类型。



在运行时,在泛型类型声明中的所有代码都在一个封闭构造类型的上下文执行,这个封闭构造类型是通过将类型实参应用到泛型声明中创建的。在泛型类型中的每个类型实参被绑定到一个特定运行时类型。所有语句和表达式的运行时处理总是针对封闭类型发生,而开放类型只发生在编译时处理。

每个封闭构造类型都有它自己的一组静态变量,它们并不被其他封闭类型共享。因为在运行时不存在开放类型,所以开放类型没有关联的静态变量。如果两个封闭构造类型是从同一个类型声明构造的,并且对应的类型实参也是相同的类型,那么它们就是相同的类型。

20.5.3构造类型的基类和接口

构造类类型有一个直接基类,就像是一个简单类类型。如果泛型类声明没有指定基类,其基类为object。如果基类在泛型类声明中被指定,构造类型的基类通过将在基类声明中的每个类型参数,替代为构造类型对应类型实参而得到。给定泛型类声明

class B<U , V>{…}
class G<T>:B<string , T[]>{…}
로그인 후 복사

构造类型G的基类将会是B

相似地,构造类、结构和接口类型有一组显式的基接口。显式基接口通过接受泛型类型声明中的显式基接口声明和某种替代而形成,这种替代是将在基接口声明中的每个类型参数,替代为构造类型的对应类型实参。



一个类型的所有基类和基接口通过递归地得到中间基类和接口的基类与接口而形成。例如,给定泛型类声明

class A {…}
class B<T>:A{…}
class C<T>:B<IComparable<T>>{…}
class D<T>:C<T[]>{…}
D<int>的基类是C<int[]>,B<IComparable<int[]>>,A和object。
로그인 후 복사

20.5.4构造类型的成员

构造类型的非继承成员通过替代成员声明的类型实参,构造类型的对应类型实参而得到。

例如,给定泛型类声明

class Gen<T,U>
{
public T[,],a;
public void G(int i ,T t , Gen<U, T> gt){…}
public U Prop(get{…}) set{…}}
public int H{double d}{…}
}
로그인 후 복사

构造类型Gen>有如下的成员。

public int[,][] a;
public void G(int I , int[] t , Gen<IComparable<string>,int[] gt>){…}
public IComparable<string> Prop{get{…} set{…}}
public int H(double d){…}
로그인 후 복사

注意替代处理是基于类型声明的语义意义的,并不是简单的基于文本的替代。在泛型类声明Gen中的成员a的类型是“T的二维数组” 因此在先前实例化类型中的成员a的类型是“int型的一维数组的二维数组”或int[,][]。

构造类型的继承成员以一种相似的方法得到。首先直接基类的所有成员是已经确定的。如果基类自身是构造类型这可能包括当前规则的递归应用。然后,继承成员的每一个通过将成员声明中的每个类型参数,替代为构造类型对应类型实参而被转换。

class B<U>
{
public U F(long index){…}
}
class D<T>:B<T[]>
{
public T G(string s){…}
}
로그인 후 복사

在先前的例子中,构造类型D的非继承成员public int G(string s)通过替代类型参数T的类型实参int而得到。D也有一个从类声明B而来的继承成员。这个继承成员通过首先确定构造类型B的成员而被确定,B成员的确定是通过将U替换为替换为T[],产生public T[] F(long index)。然后类型实参int替换了类型参数T,产生继承成员public int[] F(long index)。

20.5.5构造类型的可访问性

当构造类型C的所有部分C,T1,…,TN 可访问时,那么它就是可访问的。例如,如果泛型类型名C是public,并且所有类型参数T1,…,TN也是public ,那么构造类型的可访问性也是public 。如果类型名或类型实参之一是private,那么构造类型的可访问性是private。如果类型实参之一可访问性是protected,另一个是internal,那么构造类型的可访问性仅限于该类,以及本程序集之内的子类。

20.5.6转换

构造类型遵循与非泛型类型相同的规则(§6)。当应用这些规则时,构造类型的基类和接口必须按§20.5.3中所描述的方式确定。

除了那些在§6中所描述的之外,构造引用类型之间不存在特别的转换。尤其是,不像数组类型,构造引用类型不允许“co-variant”转换。也就是说,类型List不能转换到类型List(无论是隐式或显式)即使是B派生于A也是如此。同样,也不存在从List到List的转换。

对于这一点的基本原理是很简单的:如果可以转换到List,很显然你可以存储一个类型A的值到这个list中。这将破坏在List类型中的每个对象总是类型B的值这种不变性,或者当在集合类上赋值时,将出现不可预料的错误。

转换的行为和运行时类型检查演示如下。

class A {…}
class B:A{…}
class Colletion{…}
class List<T>:Collection{…}
class Test
{
void F()
{
List<A> listA = new List<A>();
List<B> listB= new List<B>();
Collection c1 = listA; //OK,List<A>是一个集合
Collection c2 = listB; //OK,List<B>是一个集合
List<A> a1 = listB; //错误,没有隐式的转换
List<A> a2 = (List<A>)listB; //错误,没有显式的转换
}
}
로그인 후 복사

20.5.7System.Nullable类型

在.NET基类库中定义了泛型结构类型System.Nullable泛型结构类型,它表示一个类型T的值可以为null。System.Nullable类型在很多情形下是很有用的,例如用于指示数据库表的可空列,或者XML元素中的可选特性。

可以从一个null类型向任何由System.Nullable类型构造的类型作隐式地转换。这种转换的结果就是System.Nullable的默认值。也就是说,可以这样写

Nullable<int> x = null;
Nullable<string> y = null;
로그인 후 복사

和下面的写法相同。

Nullable<int> x = Nullable<int>.default;
Nullable<string> y = Nullable<string>.default;
로그인 후 복사

20.5.8使用别名指令

使用别名可以命名一个封闭构造类型,但不能命名一个没有提供类型实参的泛型类型声明。例如

namespace N1
{
class A<T>
{
class B{}
}

class C{}
}
namespace N2
{
using W = N1.A; //错误,不能命名泛型类型
using X = N1.A.B; //错误,不能命名泛型类型
using Y = N1.A<int>; //ok,可以命名封闭构造类型
using Z = N1.C; //ok
}
로그인 후 복사

20.5.9特性

开放类型不能被用于特性内的任何地方。一个封闭构造类型可以被用作特性的实参,但不能被用作特性名,因为System.Attribute不可能是泛型类声明的基类。

class A:Attribute
{
public A(Type t){…}
}
class B<T>: Attribute{} //错误,不能将Attribute用作基类
class List<T>
{
[A(typeof(T))] T t; //错误,在特性中有开放类型
}
class X 
{
[A(typeof(List<int>))] int x; //ok,封闭构造类型
[B<int>] int y; //错误,无效的特性名字
}
로그인 후 복사

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


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

핫 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 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

C 언어로 다양한 기호를 사용하는 방법 C 언어로 다양한 기호를 사용하는 방법 Apr 03, 2025 pm 04:48 PM

C 언어 커버 산술, 할당, 조건, 논리, 비트 연산자 등의 기호의 사용 방법은 기본 수학 연산에 사용되며, 할당 연산자는 할당 및 추가, 곱하기, 분할 할당에 사용되며, 곱하기 및 분할 할당에 사용되며, 조건에 따라 조건 운영자가 사용되며, 비트 오퍼레이터에 사용되며, 스페셜 오퍼레이터는 비트 수준의 운영에 사용됩니다. 포인터, 파일 종료 마커 및 비수통 값.

C 현에서 숯의 역할은 무엇입니까? C 현에서 숯의 역할은 무엇입니까? Apr 03, 2025 pm 03:15 PM

C에서 숯 유형은 문자열에 사용됩니다. 1. 단일 문자를 저장하십시오. 2. 배열을 사용하여 문자열을 나타내고 널 터미네이터로 끝납니다. 3. 문자열 작동 함수를 통해 작동합니다. 4. 키보드에서 문자열을 읽거나 출력하십시오.

멀티 스레딩과 비동기 C#의 차이 멀티 스레딩과 비동기 C#의 차이 Apr 03, 2025 pm 02:57 PM

멀티 스레딩과 비동기식의 차이점은 멀티 스레딩이 동시에 여러 스레드를 실행하는 반면, 현재 스레드를 차단하지 않고 비동기식으로 작업을 수행한다는 것입니다. 멀티 스레딩은 컴퓨팅 집약적 인 작업에 사용되며 비동기식은 사용자 상호 작용에 사용됩니다. 멀티 스레딩의 장점은 컴퓨팅 성능을 향상시키는 것이지만 비동기의 장점은 UI 스레드를 차단하지 않는 것입니다. 멀티 스레딩 또는 비동기식을 선택하는 것은 작업의 특성에 따라 다릅니다. 계산 집약적 작업은 멀티 스레딩을 사용하고 외부 리소스와 상호 작용하고 UI 응답 성을 비동기식으로 유지 해야하는 작업을 사용합니다.

C 언어로 Char Array를 사용하는 방법 C 언어로 Char Array를 사용하는 방법 Apr 03, 2025 pm 03:24 PM

char 어레이는 문자 시퀀스를 C 언어로 저장하고 char array_name [size]로 선언됩니다. 액세스 요소는 첨자 연산자를 통해 전달되며 요소는 문자열의 끝점을 나타내는 널 터미네이터 '\ 0'으로 끝납니다. C 언어는 strlen (), strcpy (), strcat () 및 strcmp ()와 같은 다양한 문자열 조작 함수를 제공합니다.

C 언어로 특수 문자를 처리하는 방법 C 언어로 특수 문자를 처리하는 방법 Apr 03, 2025 pm 03:18 PM

C 언어에서 특수 문자는 다음과 같은 탈출 시퀀스를 통해 처리됩니다. \ n 라인 브레이크를 나타냅니다. \ t는 탭 문자를 의미합니다. char c = '\ n'과 같은 특수 문자를 나타 내기 위해 탈출 시퀀스 또는 문자 상수를 사용하십시오. 백 슬래시는 두 번 탈출해야합니다. 다른 플랫폼과 컴파일러마다 다른 탈출 시퀀스가있을 수 있습니다. 문서를 참조하십시오.

C 언어에서 Char와 WCHAR_T의 차이 C 언어에서 Char와 WCHAR_T의 차이 Apr 03, 2025 pm 03:09 PM

C 언어에서 char와 wchar_t의 주요 차이점은 문자 인코딩입니다. char ascii를 사용하거나 ascii를 확장하고, wchar_t는 유니 코드를 사용합니다. Char는 1-2 바이트를 차지하고 WCHAR_T는 2-4 바이트를 차지합니다. Char는 영어 텍스트에 적합하며 WCHAR_T는 다국어 텍스트에 적합합니다. Char_t는 널리 지원되며, 컴파일러 및 운영 체제가 유니 코드를 지원하는지 여부에 따라 다릅니다. Char는 문자 범위가 제한되며 WCHAR_T는 더 큰 문자 범위를 가지며 특수 함수는 산술 작업에 사용됩니다.

C 언어로 Char를 변환하는 방법 C 언어로 Char를 변환하는 방법 Apr 03, 2025 pm 03:21 PM

C 언어에서 숯 유형 변환은 다른 유형으로 직접 변환 할 수 있습니다. 캐스팅 : 캐스팅 캐릭터 사용. 자동 유형 변환 : 한 유형의 데이터가 다른 유형의 값을 수용 할 수 있으면 컴파일러가 자동으로 변환됩니다.

C 언어 합계의 기능은 무엇입니까? C 언어 합계의 기능은 무엇입니까? Apr 03, 2025 pm 02:21 PM

C 언어에는 내장 합계 기능이 없으므로 직접 작성해야합니다. 합계는 배열 및 축적 요소를 가로 질러 달성 할 수 있습니다. 루프 버전 : 루프 및 배열 길이를 사용하여 계산됩니다. 포인터 버전 : 포인터를 사용하여 배열 요소를 가리키며 효율적인 합계는 자체 증가 포인터를 통해 달성됩니다. 동적으로 배열 버전을 할당 : 배열을 동적으로 할당하고 메모리를 직접 관리하여 메모리 누출을 방지하기 위해 할당 된 메모리가 해제되도록합니다.

See all articles