जेनेरिक विशेषता प्रकारों के लिए C # मना क्यों करता है?


510

यह एक संकलन-समय अपवाद का कारण बनता है:

public sealed class ValidatesAttribute<T> : Attribute
{

}

[Validates<string>]
public static class StringValidation
{

}

मुझे लगता है कि C # सामान्य विशेषताओं का समर्थन नहीं करता है। हालाँकि, बहुत Googling के बाद, मुझे इसका कारण पता नहीं लग सकता है।

क्या किसी को पता है कि सामान्य प्रकार क्यों नहीं प्राप्त कर सकते हैं Attribute? कोई सिद्धांत?


17
आप कर सकते हैं [
मान्यताओं

20
भले ही यह इस सवाल का बहुत देर से जोड़ है, लेकिन यह दुखद है कि न केवल खुद को बल्कि एट्रिब्यूट क्लासेस को भी शामिल किया गया है (जो कि किसी भी तरह से एट्रिब्यूट नहीं किया जा सकता है) को अलविदा नहीं किया गया है, जैसे कि: abstract class Base<T>: Attribute {}जिसका इस्तेमाल नॉन बनाने के लिए किया जा सकता है। जेनेरिक व्युत्पन्न वर्ग इस तरह से हैं:class Concrete: Base<MyType> {}
लुसेरो

88
मैं जेनेरिक विशेषताओं और विशेषताओं को स्वीकार करने के लिए तरसता हूं। चीजों की कल्पना करें [DependsOnProperty<Foo>(f => f.Bar)]या [ForeignKey<Foo>(f => f.IdBar)]...
Jacek Gorgo

3
यह एक ऐसी स्थिति में उपयोगी होगा, जिसका मैंने अभी सामना किया है; एक LinkedValueAttribute बनाने के लिए यह अच्छा होगा कि एक सामान्य प्रकार को स्वीकार किया जाए और उस प्रकार को वास्तविक मूल्य पर लागू किया जाए। मैं इसे किसी अन्य एनम के "डिफॉल्ट" मान को निर्दिष्ट करने के लिए एनम के लिए उपयोग कर सकता हूं जिसे इस एनम मान को चुना जाना चाहिए। इनमें से कई विशेषताओं को विभिन्न प्रकारों के लिए निर्दिष्ट किया जा सकता है, और मुझे जिस प्रकार की आवश्यकता है उसके आधार पर मुझे वह मूल्य मिल सकता है जो मुझे चाहिए। मैं टाइप और ऑब्जेक्ट का उपयोग करने के लिए इसे सेट कर सकता हूं लेकिन दृढ़ता से टाइप किया जाना एक बहुत बड़ा प्लस होगा।
कीथ्स

10
यदि आप थोड़ा सा IL का बुरा नहीं मानते हैं, तो यह आशाजनक लगता है
जारोड डिक्सन

जवाबों:


358

खैर, मैं जवाब नहीं दे सकता कि यह क्यों उपलब्ध नहीं है, लेकिन मैं पुष्टि कर सकता हूं कि यह सीएलआई मुद्दा नहीं है। सीएलआई कल्पना इसका उल्लेख नहीं करती है (जहां तक ​​मैं देख सकता हूं) और यदि आप सीधे आईएल का उपयोग करते हैं तो आप एक सामान्य विशेषता बना सकते हैं। C # 3 कल्पना का हिस्सा जो इसे प्रतिबंधित करता है - धारा 10.1.4 "क्लास बेस स्पेसिफिकेशन" कोई औचित्य नहीं देता है।

एनोटामा सीएमएमए 2 # कल्पना किसी भी उपयोगी जानकारी नहीं देती है, हालांकि यह अनुमति नहीं है का एक उदाहरण प्रदान करता है।

एनोटेट सी # 3 कल्पना की मेरी कॉपी कल आनी चाहिए ... मैं देखूंगा कि क्या कोई और जानकारी देता है। वैसे भी, यह निश्चित रूप से एक रनटाइम के बजाय एक भाषा का निर्णय है।

संपादित करें: एरिक लिपर्ट (पैराफ्रास्ड) से उत्तर: कोई विशेष कारण नहीं है, एक उपयोग के मामले के लिए भाषा और संकलक दोनों में जटिलता से बचने के अलावा, जो बहुत अधिक मूल्य नहीं जोड़ता है।


139
"भाषा और संकलक दोनों में जटिलता से बचने के लिए" ... और यह कि हमें सह और
विरोधाभासी

254
"ऐसे मामले का उपयोग करें जो अधिक मूल्य नहीं जोड़ता है"? यह एक व्यक्तिपरक राय है, यह मुझे बहुत मूल्य प्रदान कर सकता है!
जॉन क्रूगर

34
वह चीज जो मुझे इस सुविधा के बारे में सबसे अधिक परेशान करती है, [प्रॉपर्टी रेफरेंस (x => x.SomeProperty)] जैसी चीजें करने में सक्षम नहीं है। इसके बजाय, आपको जादू के तार और टाइपोफ () की आवश्यकता है, जो मुझे लगता है कि तरह तरह के बेकार हैं।
असबजर्न उल्सबर्ग

13
@ जॉन: मुझे लगता है कि आप एक नई भाषा सुविधा को डिजाइन करने, निर्दिष्ट करने, लागू करने और परीक्षण करने की लागत को बहुत कम आंकते हैं।
जॉन स्कीट Jon

14
मैं सिर्फ @ टिमवी के बचाव में जोड़ना चाहता हूं कि यह एकमात्र ऐसी जगह नहीं है, जिस पर उनकी चर्चा हो रही है , और इस सवाल पर 13K विचार स्वस्थ स्तर का अभिप्राय है। इसके अलावा: एक आधिकारिक उत्तर पाने के लिए धन्यवाद, जॉन।
जॉर्डन ग्रे

84

एक विशेषता वर्ग को संकलन-समय पर सजाती है, लेकिन एक सामान्य वर्ग को रनटाइम तक अपनी अंतिम प्रकार की जानकारी प्राप्त नहीं होती है। चूंकि विशेषता संकलन को प्रभावित कर सकती है, इसलिए इसे संकलन समय पर "पूर्ण" होना चाहिए।

अधिक जानकारी के लिए इस MSDN लेख को देखें।


3
लेख बताता है कि वे संभव नहीं हैं, लेकिन बिना किसी कारण के। मैं आपके उत्तर को वैचारिक रूप से समझता हूं। क्या आप इस मुद्दे पर किसी और आधिकारिक दस्तावेज के बारे में जानते हैं?
ब्रायन वत्स

2
लेख इस तथ्य को कवर करता है कि आईएल में अभी भी जेनेरिक प्लेसहोल्डर शामिल हैं जिन्हें रनटाइम पर वास्तविक प्रकार के साथ प्रतिस्थापित किया गया है। बाकी सब मेरे द्वारा अनुमान लगाया गया था ... :)
गेलेक्टिककोवेबॉय

1
जो इसके लायक है, वीबी एक ही बाधा को लागू करता है: "सामान्य प्रकार में सामान्य या समाहित करने वाली कक्षाएं एक विशेषता वर्ग से विरासत में नहीं मिल सकती हैं।"
गैलेक्टिक

1
ECMA-334, धारा 14.16 में कहा गया है "नीचे सूचीबद्ध संदर्भों में लगातार अभिव्यक्ति की आवश्यकता होती है और इसे व्याकरण में निरंतर-अभिव्यक्ति का उपयोग करके इंगित किया जाता है। इन संदर्भों में, संकलन-समय त्रुटि तब होती है जब कोई अभिव्यक्ति पूरी तरह से संकलन पर मूल्यांकन नहीं कर सकती है- समय।" गुण सूची में हैं।
गैलेक्टिक

4
यह एक अन्य उत्तर से विरोधाभास लगता है जो बताता है कि आईएल इसकी अनुमति देगा। ( stackoverflow.com/a/294259/3195477 )
UUDdLrLrSs

21

मुझे नहीं पता कि इसकी अनुमति क्यों नहीं है, लेकिन यह एक संभव समाधान है

[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
{
    ....
}

3
दुर्भाग्य से, आप विशेषता का उपभोग करते समय संकलन-समय टाइपिंग खो देते हैं। कल्पना कीजिए कि विशेषता सामान्य प्रकार का कुछ बनाती है। आप इसके चारों ओर काम कर सकते हैं, लेकिन यह अच्छा होगा; यह उन सहज ज्ञान युक्त चीजों में से एक है जिन्हें आप आश्चर्यचकित करते हैं कि आप ऐसा नहीं कर सकते, जैसे विचरण (वर्तमान में)।
ब्रायन वत्स

14
दुख की बात यह है कि ऐसा नहीं करने की कोशिश कर रहा है इसलिए मुझे यह एसओ सवाल मिला। मुझे लगता है कि मुझे टाइपोफ से निपटने के लिए बस छड़ी करनी होगी। ऐसा लगता है कि जेनरिक के इतने लंबे समय तक अस्तित्व में रहने के बाद अब यह एक गंदा कीवर्ड है।
क्रिस मैरिकिक

13

यह वास्तव में सामान्य नहीं है और आपको अभी भी प्रति प्रकार विशिष्ट विशेषता वर्ग लिखना है, लेकिन आप थोड़ा रक्षात्मक रूप से कोड करने के लिए सामान्य आधार इंटरफ़ेस का उपयोग करने में सक्षम हो सकते हैं, अन्यथा आवश्यकता से कम कोड लिख सकते हैं, बहुरूपता का लाभ प्राप्त कर सकते हैं आदि।

//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
{

}

8

यह एक बहुत अच्छा सवाल है। विशेषताओं के साथ मेरे अनुभव में, मुझे लगता है कि बाधा जगह में है, क्योंकि जब एक विशेषता को दर्शाती यह एक शर्त है जो आप सभी संभावित प्रकार क्रमपरिवर्तन के लिए जाँच करने के लिए होगा बनाने होगा: typeof(Validates<string>),typeof(Validates<SomeCustomType>) , आदि ...

मेरी राय में, यदि प्रकार के आधार पर एक कस्टम सत्यापन की आवश्यकता होती है, तो एक विशेषता सर्वोत्तम दृष्टिकोण नहीं हो सकती है।

शायद एक सत्यापन वर्ग जो एक SomeCustomValidationDelegateया ISomeCustomValidatorएक पैरामीटर के रूप में लेता है, एक बेहतर दृष्टिकोण होगा।


मैं आपसे सहमत हुँ। मेरे पास यह प्रश्न लंबे समय से है, और मैं वर्तमान में एक सत्यापन प्रणाली का निर्माण कर रहा हूं। मैंने सवाल पूछने के लिए अपनी वर्तमान शब्दावली का उपयोग किया, लेकिन इस तंत्र के आधार पर एक दृष्टिकोण को लागू करने का कोई इरादा नहीं है।
ब्रायन वत्स

मैं एक ही लक्ष्य के लिए एक डिजाइन पर काम करते समय इस पर ठोकर खाई: सत्यापन। मैं इसे एक ऐसे तरीके से करने की कोशिश कर रहा हूं जो स्वचालित रूप से दोनों का विश्लेषण करना आसान है (यानी, आप पुष्टि के लिए आवेदन में सत्यापन का वर्णन करने वाली एक रिपोर्ट उत्पन्न कर सकते हैं) और एक मानव द्वारा कोड को विज़ुअलाइज़ करके। यदि विशेषता नहीं है, तो मुझे यकीन नहीं है कि सबसे अच्छा समाधान क्या होगा ... मैं अभी भी विशेषता डिजाइन की कोशिश कर सकता हूं, लेकिन मैन्युअल रूप से टाइप-विशिष्ट विशेषताओं की घोषणा कर सकता हूं। यह थोड़ा अधिक काम है, लेकिन उद्देश्य सत्यापन नियमों को जानने की विश्वसनीयता के लिए है (और पुष्टि के लिए उन पर रिपोर्ट करने में सक्षम है)।
बंबाम्स

4
आप सामान्य प्रकार की परिभाषाओं के विरुद्ध जांच कर सकते हैं (जैसे टाइपोफ़ (मान्य <>)) ...
मेल्विन

5

यह वर्तमान में सी # भाषा की विशेषता नहीं है, हालांकि आधिकारिक सी # भाषा रेपो पर बहुत चर्चा है

से कुछ मीटिंग नोट्स :

भले ही यह सिद्धांत रूप में काम करेगा, रनटाइम के अधिकांश संस्करणों में बग हैं ताकि यह सही तरीके से काम न करे (यह कभी भी व्यायाम नहीं किया गया था)।

हमें यह समझने के लिए एक तंत्र की आवश्यकता है कि यह किस लक्ष्य रनटाइम पर काम करता है। हमें कई चीजों के लिए जरूरत है, और वर्तमान में उस पर विचार कर रहे हैं। तब तक, हम इसे नहीं ले सकते।

प्रमुख C # संस्करण के लिए उम्मीदवार, अगर हम पर्याप्त संख्या में रनटाइम संस्करण बना सकते हैं।


1

मेरा काम कुछ इस तरह है:

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; }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.