टाइप टेस्टी है तो टेस्ट कैसे करें


162

मेरे पास कोड का एक ब्लॉक है जो एक प्रकार को एचटीएमएल टैग में क्रमबद्ध करता है।

Type t = typeof(T); // I pass <T> in as a paramter, where myObj is of type T
tagBuilder.Attributes.Add("class", t.Name);
foreach (PropertyInfo prop in t.GetProperties())
{
    object propValue = prop.GetValue(myObj, null);
    string stringValue = propValue != null ? propValue.ToString() : String.Empty;
    tagBuilder.Attributes.Add(prop.Name, stringValue);
}

यह महान काम करता है, को छोड़कर मैं इसे केवल आदिम प्रकार, जैसे के लिए ऐसा करना चाहते हैं int, double, boolआदि, और अन्य प्रकार है कि आदिम नहीं हैं, लेकिन जैसे आसानी से श्रृंखलाबद्ध किया जा सकता है string। मैं चाहता हूं कि यह सूची और अन्य कस्टम प्रकारों की तरह सब कुछ अनदेखा कर दे।

क्या कोई सुझाव दे सकता है कि मैं यह कैसे करूं? या क्या मुझे उन प्रकारों को निर्दिष्ट करने की आवश्यकता है जिन्हें मैं कहीं अनुमति देना चाहता हूं और यह देखने के लिए कि क्या इसकी अनुमति है, संपत्ति के प्रकार पर स्विच करें? यह थोड़ा गड़बड़ है, इसलिए यह अच्छा होगा अगर मैं एक कठिन रास्ता तय करूं।


12
System.Stringएक आदिम प्रकार नहीं है।
स्लाक्स

3
इसका बेहतर तरीका यह है कि जेनरिक का इस्तेमाल बिल्कुल न किया जाए। यदि आप कानूनी पैरामीटर प्रकारों के रूप में छोटी संख्या का समर्थन करते हैं, तो बस कई अतिभार हैं। यदि आप ISERializable को लागू करने वाले किसी भी प्रकार का समर्थन करते हैं, तो एक गैर-जेनेरिक विधि लिखें जो ISerializable लेता है। उन चीजों के लिए जेनेरिक का उपयोग करें जो वास्तव में सामान्य हैं ; यदि प्रकार वास्तव में मायने रखता है, तो शायद यह सामान्य नहीं है।
एरिक लिपर्ट

@ एरिक: धन्यवाद, मैं भी सोच रहा हूं कि क्या आप संख्यात्मक मानदंड के साथ एक ही मानदंड का उपयोग कर सकते हैं? उदाहरण के लिए गणितीय कार्यों को लिखने के लिए जो सभी संख्यात्मक प्रकारों का समर्थन करते हैं, जैसे कि औसत, योग, आदि। क्या उन्हें जेनेरिक या अधिभार का उपयोग करके लागू किया जाना चाहिए? क्या यह मायने रखता है कि कार्यान्वयन समान है या नहीं? क्योंकि यह किसी भी संख्यात्मक प्रकार के लिए औसत, योग के लिए बहुत समान ऑपरेशन है, है ना?
जोन वेंज

1
@ जोआन: विभिन्न ऑपरेटरों को लागू करने के लिए विवश प्रकारों पर सामान्य अंकगणितीय तरीकों को लिखने में सक्षम होना एक बार-बार अनुरोधित सुविधा है, लेकिन इसके लिए सीएलआर समर्थन की आवश्यकता होती है और यह आश्चर्यजनक रूप से जटिल है। हम इसे भाषा के भविष्य के संस्करणों के लिए विचार कर रहे हैं, लेकिन कोई वादा नहीं।
एरिक लिपर्ट

जवाबों:


184

आप संपत्ति का उपयोग कर सकते हैं Type.IsPrimitive, लेकिन लापरवाह रहें क्योंकि कुछ प्रकार हैं जो हम सोच सकते हैं कि आदिम हैं, लेकिन वे उदाहरण के लिए Decimalऔर String

1 संपादित करें: नमूना कोड जोड़ा गया

यहाँ एक नमूना कोड है:

if (t.IsPrimitive || t == typeof(Decimal) || t == typeof(String) || ... )
{
    // Is Primitive, or Decimal, or String
}

संपादित करें 2: As @SLaks टिप्पणियों के , अन्य प्रकार भी हैं जो शायद आप आदिम के रूप में भी व्यवहार करना चाहते हैं। मुझे लगता है कि आपको इस बदलाव को एक-एक करके जोड़ना होगा

संपादित करें 3: IsPrimitive = (बूलियन, बाइट, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, चार, डबल और एकल), Anther आदिम-प्रकार की जाँच करने के लिए टाइप करें (t == typeTime (DateTime) ))


12
और शायद DateTime,, TimeSpanऔर DateTimeOffset
SLaks

मम्म्म… हाँ, आप सही कह रहे हैं। मुझे लगता है कि हमें कुछ और संभावनाओं को जोड़ना होगा
जेवियर

2
आपको तार्किक या ( ||) का उपयोग करने की आवश्यकता है , न कि बिटवाइज़ या ( |)।
एसके

42
यहाँ एक विस्तार विधि है जो मैंने @ जेवियर और माइकल पेटिटो द्वारा दिए गए परीक्षणों को आसानी से चलाने के लिए लिखी है: gist.github.com/3330614
जोनाथन

5
आप संपत्ति Type.IsValueType का उपयोग कर सकते हैं और केवल स्ट्रिंग के लिए चेक जोड़ सकते हैं ।
माटेयो मिग्लियोर

57

मैंने इसी तरह के समाधान की तलाश करते हुए बस यह प्रश्न पाया, और सोचा कि आप निम्नलिखित दृष्टिकोण का उपयोग करने में दिलचस्पी ले सकते हैं System.TypeCodeऔर System.Convert

ऐसे किसी भी प्रकार को क्रमबद्ध करना आसान है जो किसी System.TypeCodeअन्य से मैप किया जाता है System.TypeCode.Object, इसलिए आप ऐसा कर सकते हैं:

object PropertyValue = ...
if(Convert.GetTypeCode(PropertyValue) != TypeCode.Object)
{
    string StringValue = Convert.ToString(PropertyValue);
    ...
}

इस दृष्टिकोण के साथ लाभ यह है कि आपको हर दूसरे स्वीकार्य गैर-आदिम प्रकार का नाम नहीं देना है। आप किसी भी प्रकार को संभालने के लिए उपरोक्त कोड को थोड़ा संशोधित कर सकते हैं जो IConvertible को लागू करता है।


2
यह बहुत अच्छा है, मुझे Guidस्वयं अपने उद्देश्यों के लिए जोड़ना होगा (मेरी परिभाषा में एक आदिम के रूप में)।
एरिक फिलिप्स

56

हम इसे अपने ORM में इस तरह करते हैं:

Type t;
bool isPrimitiveType = t.IsPrimitive || t.IsValueType || (t == typeof(string));

मुझे पता है कि उपयोग IsValueTypeकरना सबसे अच्छा विकल्प नहीं है (आपके पास बहुत जटिल संरचनाएं हो सकती हैं), लेकिन यह 99% मामलों में काम करता है (और इसमें Nullables भी शामिल है)।


6
यदि आप IsValueType का उपयोग कर रहे हैं तो आपको IsPrimitive की आवश्यकता क्यों है? क्या सभी आदिम मूल्य प्रकार नहीं हैं?
जोएलफैन

5
@JoelFan दशमलव प्रकार में IsPrimitive झूठा है, लेकिन IsValueType सच है
xhafan

3
@xhafan: आप गलत प्रश्न का उत्तर देते हैं। decimalउस संबंध में सभी संरचनाएं समान हैं । लेकिन क्या एक प्रकार है जिसके लिए IsPrimitiveरिटर्न है trueलेकिन IsValueTypeरिटर्न false? यदि ऐसा कोई प्रकार नहीं हैं, तो t.IsPrimitiveपरीक्षण अनावश्यक है।
लीई

6
@ आप सही हैं, हर आदिम प्रकार IsValueTypeसही हो गया है, इसलिए जाँच IsPrimitiveकी आवश्यकता नहीं है। चीयर्स!
xhafan

1
@ वे कभी नहीं। आपके पास एक गैर-आदिम मूल्य प्रकार हो सकता है, जिस स्थिति में गुणों के अलग-अलग मूल्य हैं।
माइकल पेटिटो

38

@ रॉनी ओवरबी प्रतिक्रिया और @jonathanconway टिप्पणी से, मैंने यह विधि लिखी जो Nullable के लिए काम करती है, और उपयोगकर्ता संरचनाओं को बाहर करती है।

public static bool IsSimpleType(Type type)
{
    return
        type.IsPrimitive ||
        new Type[] {
            typeof(string),
            typeof(decimal),
            typeof(DateTime),
            typeof(DateTimeOffset),
            typeof(TimeSpan),
            typeof(Guid)
        }.Contains(type) ||
        type.IsEnum ||
        Convert.GetTypeCode(type) != TypeCode.Object ||
        (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>) && IsSimpleType(type.GetGenericArguments()[0]))
        ;
}

निम्नलिखित TestCase के साथ:

struct TestStruct
{
    public string Prop1;
    public int Prop2;
}

class TestClass1
{
    public string Prop1;
    public int Prop2;
}

enum TestEnum { TheValue }

[Test]
public void Test1()
{
    Assert.IsTrue(IsSimpleType(typeof(TestEnum)));
    Assert.IsTrue(IsSimpleType(typeof(string)));
    Assert.IsTrue(IsSimpleType(typeof(char)));
    Assert.IsTrue(IsSimpleType(typeof(Guid)));

    Assert.IsTrue(IsSimpleType(typeof(bool)));
    Assert.IsTrue(IsSimpleType(typeof(byte)));
    Assert.IsTrue(IsSimpleType(typeof(short)));
    Assert.IsTrue(IsSimpleType(typeof(int)));
    Assert.IsTrue(IsSimpleType(typeof(long)));
    Assert.IsTrue(IsSimpleType(typeof(float)));
    Assert.IsTrue(IsSimpleType(typeof(double)));
    Assert.IsTrue(IsSimpleType(typeof(decimal)));

    Assert.IsTrue(IsSimpleType(typeof(sbyte)));
    Assert.IsTrue(IsSimpleType(typeof(ushort)));
    Assert.IsTrue(IsSimpleType(typeof(uint)));
    Assert.IsTrue(IsSimpleType(typeof(ulong)));

    Assert.IsTrue(IsSimpleType(typeof(DateTime)));
    Assert.IsTrue(IsSimpleType(typeof(DateTimeOffset)));
    Assert.IsTrue(IsSimpleType(typeof(TimeSpan)));

    Assert.IsFalse(IsSimpleType(typeof(TestStruct)));
    Assert.IsFalse(IsSimpleType(typeof(TestClass1)));

    Assert.IsTrue(IsSimpleType(typeof(TestEnum?)));
    Assert.IsTrue(IsSimpleType(typeof(char?)));
    Assert.IsTrue(IsSimpleType(typeof(Guid?)));

    Assert.IsTrue(IsSimpleType(typeof(bool?)));
    Assert.IsTrue(IsSimpleType(typeof(byte?)));
    Assert.IsTrue(IsSimpleType(typeof(short?)));
    Assert.IsTrue(IsSimpleType(typeof(int?)));
    Assert.IsTrue(IsSimpleType(typeof(long?)));
    Assert.IsTrue(IsSimpleType(typeof(float?)));
    Assert.IsTrue(IsSimpleType(typeof(double?)));
    Assert.IsTrue(IsSimpleType(typeof(decimal?)));

    Assert.IsTrue(IsSimpleType(typeof(sbyte?)));
    Assert.IsTrue(IsSimpleType(typeof(ushort?)));
    Assert.IsTrue(IsSimpleType(typeof(uint?)));
    Assert.IsTrue(IsSimpleType(typeof(ulong?)));

    Assert.IsTrue(IsSimpleType(typeof(DateTime?)));
    Assert.IsTrue(IsSimpleType(typeof(DateTimeOffset?)));
    Assert.IsTrue(IsSimpleType(typeof(TimeSpan?)));

    Assert.IsFalse(IsSimpleType(typeof(TestStruct?)));
}

1
यह एक अच्छा तरीका है, लेकिन Enumइसका समर्थन नहीं किया गया है, इसका enum MyEnum { EnumValue }उपयोग और उपयोग करके परीक्षण करें MyEnum। @ जोनाथन भी उपयोग कर रहा है type.IsValueType। इसके साथ Enumsही सही तरीके से पता लगाया जाता है, लेकिन यह भी Structs। तो देखो कि तुम क्या आदिम चाहते हो।
एपफेलुकाच

1
@Apfelkuacha: आप पूरी तरह से सही हैं। लेकिन इसका उपयोग करने के बजाय type.IsValueType, बस क्यों नहीं जोड़ा जाता है type.IsEnum?
Xav987

तुम पूर्ण रूप से सही हो। type.IsEnumयह भी संभव है। मैंने आपकी पोस्ट पर एक संपादन का सुझाव दिया है :)
Apfelkuacha

16

यहाँ है कि मैं यह कैसे किया।

   static class PrimitiveTypes
   {
       public static readonly Type[] List;

       static PrimitiveTypes()
       {
           var types = new[]
                          {
                              typeof (Enum),
                              typeof (String),
                              typeof (Char),
                              typeof (Guid),

                              typeof (Boolean),
                              typeof (Byte),
                              typeof (Int16),
                              typeof (Int32),
                              typeof (Int64),
                              typeof (Single),
                              typeof (Double),
                              typeof (Decimal),

                              typeof (SByte),
                              typeof (UInt16),
                              typeof (UInt32),
                              typeof (UInt64),

                              typeof (DateTime),
                              typeof (DateTimeOffset),
                              typeof (TimeSpan),
                          };


           var nullTypes = from t in types
                           where t.IsValueType
                           select typeof (Nullable<>).MakeGenericType(t);

           List = types.Concat(nullTypes).ToArray();
       }

       public static bool Test(Type type)
       {
           if (List.Any(x => x.IsAssignableFrom(type)))
               return true;

           var nut = Nullable.GetUnderlyingType(type);
           return nut != null && nut.IsEnum;
       }
   }

@RonnieOverby। क्या IsAssignableFromआपके परीक्षण में शामिल होने के बजाय कोई विशेष कारण है ?
जॉनी 5

6

इसके अलावा एक अच्छी संभावना:

private static bool IsPrimitiveType(Type type)
{
    return (type == typeof(object) || Type.GetTypeCode(type) != TypeCode.Object);
}

प्रत्येक उदाहरण Typeमें एक संपत्ति होती है जिसे IsPrimitive कहा जाता है । आपको इसके बजाय इसका उपयोग करना चाहिए।
रेनन

3
न तो Stringहै और न ही Decimalपुरातन है।
k3flo

यह मेरे लिए काम करता है, लेकिन मैंने इसका नाम बदलकर IsClrType कर दिया है ताकि मौजूदा के साथ इसका अर्थ भ्रमित न किया जा सके। टाइप वर्ग पर
प्रभावी

1
उदाहरण के लिए, यह गाइड या टाइमस्पैन नहीं लेगा।
स्टैनिस्लाव

3

मान लें कि आपके पास फ़ंक्शन हस्ताक्षर इस तरह हैं:

void foo<T>() 

आप केवल मूल्य प्रकारों की अनुमति देने के लिए एक सामान्य बाधा जोड़ सकते हैं:

void foo<T>() where T : struct

ध्यान दें कि यह न केवल टी के लिए आदिम प्रकार की अनुमति देता है, बल्कि किसी भी प्रकार का मूल्य है।


2

मुझे उन्हें एक्सएमएल को निर्यात करने के उद्देश्यों के लिए प्रकार को क्रमबद्ध करने की आवश्यकता थी। ऐसा करने के लिए, मैंने ऑब्जेक्ट के माध्यम से पुनरावृत्ति की और उन क्षेत्रों का चयन किया जो आदिम, enum, मूल्य प्रकार या क्रमिक थे। यह मेरी क्वेरी का परिणाम था:

Type contextType = context.GetType();

var props = (from property in contextType.GetProperties()
                         let name = property.Name
                         let type = property.PropertyType
                         let value = property.GetValue(context,
                                     (BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Public),
                                     null, null, null)
                         where (type.IsPrimitive || type.IsEnum || type.IsValueType || type.IsSerializable)
                         select new { Name = name, Value = value});

मैंने LINQ का उपयोग प्रकारों के माध्यम से पुनरावृति करने के लिए किया, फिर एक प्रतीक तालिका में संग्रहीत करने के लिए उनका नाम और मान प्राप्त करें। कुंजी 'जहां' खंड में है जिसे मैंने प्रतिबिंब के लिए चुना है। मैंने आदिम, प्रगणित, मूल्य प्रकार और क्रमबद्ध प्रकार चुने। इस तार और DateTime वस्तुओं के लिए अनुमति के रूप में मैं के माध्यम से आने की अनुमति दी।

चीयर्स!


1

यह मेरे पुस्तकालय में है। टिप्पणियों का स्वागत है।

मैं पहले IsValueType की जांच करता हूं, क्योंकि यह सबसे प्रकार को संभालता है, फिर स्ट्रिंग को, क्योंकि यह दूसरा सबसे आम है। मैं एक ऐसे आदिम के बारे में नहीं सोच सकता, जो मूल्य प्रकार नहीं है, इसलिए मुझे नहीं पता कि अगर उस पैर पर कभी चोट लग जाए।

  Public Shared Function IsPersistable(Type As System.Type) As Boolean
    With TypeInformation.UnderlyingType(Type)
      Return .IsValueType OrElse Type = GetType(String) OrElse .IsPrimitive
    End With
  End Function

  Public Shared Function IsNullable(ByVal Type As System.Type) As Boolean
    Return (Type.IsGenericType) AndAlso (Type.GetGenericTypeDefinition() Is GetType(Nullable(Of )))
  End Function

  Public Shared Function UnderlyingType(ByVal Type As System.Type) As System.Type
    If IsNullable(Type) Then
      Return Nullable.GetUnderlyingType(Type)
    Else
      Return Type
    End If
  End Function

तो मैं इसे इस तरह उपयोग कर सकते हैं:

  Public Shared Function PersistableProperties(Item As System.Type) As IEnumerable(Of System.Reflection.PropertyInfo)
    Return From PropertyInfo In Item.GetProperties()
                     Where PropertyInfo.CanWrite AndAlso (IsPersistable(PropertyInfo.PropertyType))
                     Select PropertyInfo
  End Function

0

मैं सिर्फ अपना समाधान साझा करना चाहता हूं। शायद यह किसी के लिए उपयोगी है।

public static bool IsPrimitiveType(Type fieldType)
{
   return fieldType.IsPrimitive || fieldType.Namespace.Equals("System");
}

5
IsPrimitiveType(typeof(System.AccessViolationException)) == true
रॉनी ओवरबी

2
namespace System { class MyNonPrimitiveType { } }
रॉनी ओवरबी

0
public static bool IsPrimitiveType(object myObject)
{
   var myType = myObject.GetType();
   return myType.IsPrimitive || myType.Namespace == null ||  myType.Namespace.Equals("System");
}

NULL नाम स्थान की जाँच करना न भूलें, क्योंकि अनाम ऑब्जेक्ट में नामस्थान निर्दिष्ट नहीं है


0

यहां एक और व्यवहार्य विकल्प है।

public static bool CanDirectlyCompare(Type type)
{
    return typeof(IComparable).IsAssignableFrom(type) || type.IsPrimitive || type.IsValueType;
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.