[C#] C #이 일반 속성 유형을 금지하는 이유는 무엇입니까?

컴파일 타임 예외가 발생합니다.

public sealed class ValidatesAttribute<T> : Attribute
{

}

[Validates<string>]
public static class StringValidation
{

}

C #이 일반 속성을 지원하지 않는다는 것을 알고 있습니다. 그러나 많은 인터넷 검색 후 이유를 찾을 수없는 것 같습니다.

왜 일반 형식을 파생시킬 수 없는지 아는 사람이 Attribute있습니까? 어떤 이론?



답변

글쎄, 왜 사용할 수 없는지 대답 할 수는 없지만 CLI 문제가 아니라는 것을 확인할 수 있습니다 . CLI 스펙은 (내가 볼 수있는 한) 언급하지 않으며 IL을 직접 사용하는 경우 일반 속성을 만들 수 있습니다. 이를 금지하는 C # 3 스펙의 일부-섹션 10.1.4 “클래스 기본 스펙”은 정당성을 나타내지 않습니다.

주석이 달린 ECMA C # 2 사양은 허용되지 않는 것에 대한 예를 제공하지만 유용한 정보를 제공하지 않습니다.

주석이 달린 C # 3 사양의 사본이 내일 도착해야합니다. 자세한 정보가 있는지 확인해 보겠습니다. 어쨌든 런타임 결정이 아닌 언어 결정입니다.

편집 : Eric Lippert의 답변 (그림으로 표시) : 많은 가치를 추가하지 않는 유스 케이스의 언어와 컴파일러의 복잡성을 피하는 것을 제외하고 특별한 이유는 없습니다.


답변

속성은 컴파일 타임에 클래스를 장식하지만 일반 클래스는 런타임까지 최종 유형 정보를받지 않습니다. 이 속성은 컴파일에 영향을 줄 수 있으므로 컴파일시 “완료”해야합니다.

자세한 내용은이 MSDN 기사 를 참조하십시오.


답변

왜 허용되지 않는지 모르겠지만 가능한 해결 방법 중 하나입니다.

[AttributeUsage(AttributeTargets.Class)]
public class ClassDescriptionAttribute : Attribute
{
    public ClassDescriptionAttribute(Type KeyDataType)
    {
        _KeyDataType = KeyDataType;
    }

    public Type KeyDataType
    {
        get { return _KeyDataType; }
    }
    private Type _KeyDataType;
}


[ClassDescriptionAttribute(typeof(string))]
class Program
{
    ....
}


답변

이것은 실제로 일반적인 것은 아니며 여전히 유형별로 특정 속성 클래스를 작성해야하지만, 일반적인 기본 인터페이스를 사용하여 조금 방어 적으로 코딩하고, 필요한 것보다 적은 코드를 작성하고, 다형성의 이점을 얻을 수 있습니다.

//an interface which means it can't have its own implementation. 
//You might need to use extension methods on this interface for that.
public interface ValidatesAttribute<T>
{
    T Value { get; } //or whatever that is
    bool IsValid { get; } //etc
}

public class ValidatesStringAttribute : Attribute, ValidatesAttribute<string>
{
    //...
}
public class ValidatesIntAttribute : Attribute, ValidatesAttribute<int>
{
    //...
}

[ValidatesString]
public static class StringValidation
{

}
[ValidatesInt]
public static class IntValidation
{

}


답변

이것은 매우 좋은 질문입니다. 속성 내 경험에, 나는 속성에 반영 때 가능한 모든 유형의 순열을 확인해야하는 조건을 만들 것이기 때문에 제약 조건이 장소에 생각 : typeof(Validates<string>), typeof(Validates<SomeCustomType>), 등 …

제 생각에는 유형에 따라 사용자 지정 유효성 검사가 필요한 경우 속성이 최선의 방법이 아닐 수도 있습니다.

a SomeCustomValidationDelegate또는 ISomeCustomValidatora를 매개 변수로 사용 하는 유효성 검사 클래스가 더 나은 방법 일 수 있습니다.


답변

이것은 현재 C # 언어 기능은 아니지만 공식 C # 언어 저장소에 대한 많은 토론이 있습니다 .

에서 일부 회의 노트 :

이것이 원칙적으로 작동하더라도 대부분의 런타임 버전에는 버그가 있으므로 제대로 작동하지 않습니다 (실행되지 않았습니다).

작동하는 대상 런타임을 이해하는 메커니즘이 필요합니다. 우리는 많은 것들을 위해 그것을 필요로하며 현재 그것을보고 있습니다. 그때까지는 취할 수 없습니다.

충분한 수의 런타임 버전을 처리 할 수있는 경우 주요 C # 버전의 후보입니다.


답변

내 해결 방법은 다음과 같습니다.

public class DistinctType1IdValidation : ValidationAttribute
{
    private readonly DistinctValidator<Type1> validator;

    public DistinctIdValidation()
    {
        validator = new DistinctValidator<Type1>(x=>x.Id);
    }

    public override bool IsValid(object value)
    {
        return validator.IsValid(value);
    }
}

public class DistinctType2NameValidation : ValidationAttribute
{
    private readonly DistinctValidator<Type2> validator;

    public DistinctType2NameValidation()
    {
        validator = new DistinctValidator<Type2>(x=>x.Name);
    }

    public override bool IsValid(object value)
    {
        return validator.IsValid(value);
    }
}

...
[DataMember, DistinctType1IdValidation ]
public Type1[] Items { get; set; }

[DataMember, DistinctType2NameValidation ]
public Type2[] Items { get; set; }