다음과 같은 내용을 컴파일하지 못한 후 :
public class Gen<T> where T : System.Array
{
}
오류와 함께
제약 조건은 특수 클래스`System.Array ‘일 수 없습니다.
“특별 수업” 이 정확히 무엇인지 궁금해졌습니다 .
사람들 System.Enum
은 일반적인 제약 조건에서 지정할 때 종종 같은 종류의 오류가 발생하는 것처럼 보입니다 . 나는과 같은 결과를 얻었다 System.Object
, System.Delegate
, System.MulticastDelegate
및 System.ValueType
도합니다.
그들 중 더 있습니까? C #에서 “특수 클래스”에 대한 정보를 찾을 수 없습니다.
또한, 무엇 이며 우리가 제네릭 형식 제약 조건으로 사용할 수없는 그 클래스에 대한 특별?
답변
Roslyn 소스 코드에서는 하드 코딩 된 유형 목록처럼 보입니다.
switch (type.SpecialType)
{
case SpecialType.System_Object:
case SpecialType.System_ValueType:
case SpecialType.System_Enum:
case SpecialType.System_Delegate:
case SpecialType.System_MulticastDelegate:
case SpecialType.System_Array:
// "Constraint cannot be special class '{0}'"
Error(diagnostics, ErrorCode.ERR_SpecialTypeAsBound, syntax, type);
return false;
}
출처 : Binder_Constraints.cs IsValidConstraintType
GitHub 검색을 사용하여 찾았습니다. “제약 조건은 특수 클래스가 될 수 없습니다.”
답변
비슷한 질문에 대해 2008 년 Jon Skeet의 의견을 찾았습니다 . System.Enum
제약 조건 이 지원 되지 않는 이유입니다 .
나는 이것이 약간 벗어난 주제라는 것을 알고 있지만 그는 Eric Lippert (C # 팀)에게 그것에 대해 물었고 그들은이 답변을 제공했습니다.
우선, 당신의 추측이 맞습니다. 제약 조건에 대한 제한은 CLR이 아니라 언어의 큰 인공물입니다. (이러한 기능을 수행하면 열거 가능한 유형이 지정되는 방식과 관련하여 CLR에서 변경하고 싶은 몇 가지 사소한 사항이 있지만 대부분은 언어 작업입니다.)
둘째, 저는 개인적으로 델리게이트 제약, 열거 제약 및 오늘날 불법적 인 제약 조건을 지정하는 기능을 갖고 싶습니다. 컴파일러가 사용자를 자신으로부터 구하려고하기 때문입니다. (즉, 봉인 된 유형을 제약 조건으로 합법화하는 등의 작업입니다.)
그러나 일정 제한으로 인해 이러한 기능을 다음 버전의 언어로 제공하지 못할 수 있습니다.
답변
MSDN 에 따르면 정적 클래스 목록입니다.
컴파일러 오류 CS0702
제약 조건은 특수 클래스 ‘식별자’일 수 없습니다. 다음 유형은 제약 조건으로 사용할 수 없습니다.
- System.Object
- System.Array
- System.Delegate
- System.Enum
- System.ValueType.
답변
C # 4.0 언어 사양 (코드 : [10.1.5] 유형 매개 변수 제약 조건)에 따라 다음 두 가지를 알려줍니다.
1] 유형은 객체가 아니어야합니다. 모든 유형이 객체에서 파생되기 때문에 이러한 제약 조건은 허용되는 경우 효과가 없습니다.
2] T에 기본 제약 조건이나 유형 매개 변수 제약 조건이없는 경우 유효한 기본 클래스는 객체입니다.
제네릭 클래스를 정의 할 때 클라이언트 코드가 클래스를 인스턴스화 할 때 유형 인수에 사용할 수있는 유형의 종류에 제한을 적용 할 수 있습니다. 클라이언트 코드가 제약 조건에서 허용하지 않는 형식을 사용하여 클래스를 인스턴스화하려고하면 결과는 컴파일 타임 오류입니다. 이러한 제한을 제약이라고합니다. 제약 조건은 where 문맥 키워드를 사용하여 지정됩니다.
제네릭 유형을 참조 유형으로 제한하려면 : 클래스를 사용하십시오.
public class Gen<T> where T : class
{
}
이것은 제네릭 유형이 int 또는 struct 등과 같은 값 유형이되는 것을 금지합니다.
또한 제약 조건은 특수 클래스 ‘식별자’가 될 수 없습니다. 다음 유형은 제약 조건으로 사용할 수 없습니다.
- System.Object
- System.Array
- System.Delegate
- System.Enum
- System.ValueType.
답변
프레임 워크에는 특수 특성을 파생 된 모든 유형에 효과적으로 전달 하지만 그 특성 자체를 소유하지는 않는 특정 클래스가 있습니다 . CLR 자체는 이러한 클래스를 제약 조건으로 사용하는 것을 금지하지 않지만, 이에 제한되는 제네릭 형식은 구체적인 형식과 달리 상속되지 않은 특성을 얻지 못합니다. C #의 작성자는 이러한 동작이 일부 사람들에게 혼란을 줄 수 있고 유용성을 보지 못하기 때문에 이러한 제약 조건이 CLR 에서처럼 동작하도록 허용하기보다는 금지해야한다고 결정했습니다.
예를 들어 다음과 같이 쓸 수있는 경우 : void CopyArray<T>(T dest, T source, int start, int count)
; 하나는 유형의 인수를 예상하는 메소드 dest
와 전달할 수 있습니다 . 또한, 하나는 컴파일시의 검증이를 얻을 것 와 호환되는 배열 형했지만, 하나는 사용하여 배열의 액세스 요소 수 없을 것 연산자.source
System.Array
dest
source
[]
Array
제약 조건 으로 사용할 수없는 것은 대부분 해결하기가 매우 쉽습니다 void CopyArray<T>(T[] dest, T[] source, int start, int count)
. 이전 방법이 작동하는 거의 모든 상황에서 작동하기 때문입니다. 그러나 약점이 있습니다. 전자의 방법은 System.Array
인수가 호환되지 않는 배열 유형 인 경우를 거부하면서 인수 중 하나 또는 둘 모두가 유형 인 시나리오에서 작동 합니다. 두 인수가 모두 유형 인 오버로드를 추가하면 System.Array
코드가 허용해야하는 추가 사례를 수락 할 수 있지만 허용해서는 안되는 사례를 잘못 수락하게됩니다.
나는 대부분의 특수 제약을 불법화하기로 결정했습니다. 의미 론적 의미가 0 인 유일한 것은 System.Object
[제약으로서 합법적이라면 어떤 것이라도 그것을 만족시킬 것이기 때문에] 일 것입니다. System.ValueType
유형의 참조는 ValueType
값 유형과 실제로 공통점이 많지 않기 때문에 유용 하지 않을 수 있지만 Reflection과 관련된 경우에는 그럴듯하게 가치가있을 수 있습니다. 모두 System.Enum
와 System.Delegate
진짜 용도가 것이지만, C #의 창조자들을 생각하지 않았기 때문에 그들이 더 좋은 이유에 대해 금지하고 있습니다.
답변
다음은 C # 4th Edition을 통해 CLR에서 찾을 수 있습니다.
주요 제약
유형 매개 변수는 0 개의 1 차 제약 조건 또는 1 개의 1 차 제약 조건을 지정할 수 있습니다. 기본 제약 조건은 봉인되지 않은 클래스를 식별하는 참조 형식 일 수 있습니다. System.Object , System.Array , System.Delegate ,
System.MulticastDelegate ,
System.ValueType , System.Enum 또는 System.Void 특수 참조 유형 중 하나를 지정할 수 없습니다 . 참조 형식 제약 조건을 지정할 때 지정된 형식 인수가 같은 형식이거나 제약 조건 형식에서 파생 된 형식이 될 것이라고 컴파일러에 약속합니다.
답변
“특별한 클래스”/ “특별한 유형”에 대한 공식적인 정의가 있다고 생각하지 않습니다.
“일반”유형의 의미 체계와 함께 사용할 수없는 유형으로 생각할 수 있습니다.
- 직접 인스턴스화 할 수 없습니다.
- 사용자 정의 유형을 직접 상속 할 수 없습니다.
- 그들과 함께 작동하는 컴파일러 마법이 있습니다 (선택적으로);
- 적어도 쓸모없는 인스턴스의 직접적인 사용 (선택적으로, 위에서 제네릭을 만들었다 고 상상해보십시오. 어떤 제네릭 코드를 작성할 것입니까?)
추신 System.Void
목록에 추가하겠습니다 .