Dlaczego C# zabrania generycznych typów atrybutów?
To powoduje wyjątek w czasie kompilacji:
public sealed class ValidatesAttribute<T> : Attribute
{
}
[Validates<string>]
public static class StringValidation
{
}
Zdaję sobie sprawę, że C# nie obsługuje atrybutów generycznych. Jednak po wielu Googlach nie mogę znaleźć przyczyny.
Czy ktoś wie dlaczego typy generyczne nie mogą wywodzić się z Attribute
? Jakieś teorie?
6 answers
Cóż, nie mogę odpowiedzieć, dlaczego nie jest dostępny, ale Mogę potwierdzić, że nie jest to problem z CLI. CLI spec o tym nie wspomina (z tego co widzę) i jeśli używasz IL bezpośrednio możesz utworzyć generyczny atrybut. Część specyfikacji C # 3, która ją zakazuje-sekcja 10.1.4 "Class base specification" nie daje żadnego uzasadnienia.
Adnotowana Specyfikacja ECMA C# 2 również nie daje żadnych przydatnych informacji, chociaż dostarcza przykład tego, co nie jest dozwolone.
My Kopia specyfikacji C # 3 powinna pojawić się jutro... Zobaczę, czy to da więcej informacji. W każdym razie, jest to zdecydowanie decyzja językowa, a nie runtime.
EDIT: odpowiedź Erica Lipperta (parafrazowana): nie ma szczególnego powodu, poza uniknięciem złożoności zarówno języka, jak i kompilatora dla przypadku użycia, który nie dodaje wiele wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-18 15:46:27
Atrybut dekoruje klasę podczas kompilacji, ale Klasa generyczna nie otrzymuje informacji o końcowym typie do czasu uruchomienia. Ponieważ atrybut może wpływać na kompilację, musi być "kompletny" w czasie kompilacji.
Zobacz ten artykuł MSDN Aby uzyskać więcej informacji.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-16 19:09:59
Nie wiem, dlaczego nie jest to dozwolone, ale jest to możliwe obejście
[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
{
....
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-16 21:45:03
To nie jest tak naprawdę ogólne i nadal musisz napisać specyficzną klasę atrybutów dla typu, ale możesz być w stanie użyć ogólnego interfejsu bazowego do kodowania trochę defensywnie, napisać mniejszy Kod niż jest to wymagane, uzyskać korzyści z polimorfizmu itp.
//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
{
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-07 06:45:46
To bardzo dobre pytanie. Z mojego doświadczenia z atrybutami, myślę, że ograniczenie jest na miejscu, ponieważ rozważając atrybut stworzyłby warunek, w którym musiałbyś sprawdzić wszystkie możliwe permutacje typu: typeof(Validates<string>)
, typeof(Validates<SomeCustomType>)
, itd...
Moim zdaniem, jeśli Walidacja niestandardowa jest wymagana w zależności od typu, atrybut może nie być najlepszym podejściem.
Być może Klasa walidacji, która przyjmuje SomeCustomValidationDelegate
lub ISomeCustomValidator
jako parametr, byłaby lepsza podejdźcie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-16 19:15:04
Moje obejście Jest Takie:
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; }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-29 06:56:01