क्या यह निर्धारित करने का कोई तरीका है कि क्या कोई दिया गया है या नहीं। .NET प्रकार एक संख्या है? उदाहरण के लिए: System.UInt32/UInt16/Doubleसभी संख्याएँ हैं। मैं एक लंबे स्विच-केस से बचना चाहता हूं Type.FullName।
क्या यह निर्धारित करने का कोई तरीका है कि क्या कोई दिया गया है या नहीं। .NET प्रकार एक संख्या है? उदाहरण के लिए: System.UInt32/UInt16/Doubleसभी संख्याएँ हैं। मैं एक लंबे स्विच-केस से बचना चाहता हूं Type.FullName।
जवाबों:
इसे इस्तेमाल करे:
Type type = object.GetType();
bool isNumber = (type.IsPrimitiveImple && type != typeof(bool) && type != typeof(char));
आदिम प्रकार बूलियन, बाइट, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, चार, डबल और सिंगल हैं।
ले रहा है Guillaume के समाधान थोड़ा आगे:
public static bool IsNumericType(this object o)
{
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
उपयोग:
int i = 32;
i.IsNumericType(); // True
string s = "Hello World";
s.IsNumericType(); // False
decimalप्रकार संख्यात्मक नहीं है?
decimal है सांख्यिक। सिर्फ इसलिए कि यह एक आदिम नहीं है इसका मतलब यह नहीं है कि यह संख्यात्मक नहीं है। इसके लिए आपके कोड की आवश्यकता है।
एक स्विच का उपयोग न करें - बस एक सेट का उपयोग करें:
HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(decimal), typeof(byte), typeof(sbyte),
typeof(short), typeof(ushort), ...
};
EDIT: एक प्रकार के कोड का उपयोग करने पर इसका एक फायदा यह है कि जब नए संख्यात्मक प्रकारों को .NET (जैसे BigInteger और Complex ) में पेश किया जाता है, तो इसे समायोजित करना आसान होता है - जबकि उन प्रकारों को एक प्रकार का कोड नहीं मिलेगा।
switchबस काम नहीं करता है Type, इसलिए आप नहीं कर सकते। आप TypeCodeबेशक बदल सकते हैं , लेकिन यह एक अलग मामला है।
कोई भी समाधान Nullable को ध्यान में नहीं रखता है।
मैंने जॉन स्कीट के समाधान को थोड़ा संशोधित किया:
private static HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(int),
typeof(uint),
typeof(double),
typeof(decimal),
...
};
internal static bool IsNumericType(Type type)
{
return NumericTypes.Contains(type) ||
NumericTypes.Contains(Nullable.GetUnderlyingType(type));
}
मुझे पता है कि मैं केवल अपने हैशसेट में अशक्त जोड़ सकते हैं। लेकिन यह समाधान आपकी सूची में एक विशिष्ट अशक्त जोड़ने के लिए भूलने के खतरे से बचता है।
private static HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(int),
typeof(int?),
...
};
public static bool IsNumericType(Type type)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
हटाए गए अनुकूलन के बारे में ध्यान दें (enzi टिप्पणियाँ देखें)
और यदि आप वास्तव में इसे अनुकूलित करना चाहते हैं (पठनीयता और कुछ सुरक्षा खोना ...):
public static bool IsNumericType(Type type)
{
TypeCode typeCode = Type.GetTypeCode(type);
//The TypeCode of numerical types are between SByte (5) and Decimal (15).
return (int)typeCode >= 5 && (int)typeCode <= 15;
}
return unchecked((uint)Type.GetTypeCode(type) - 5u) <= 10u;इस प्रकार शुरू की गई शाखा को हटा देगा &&।
मूल रूप से स्कीट का समाधान लेकिन आप इसे निम्न प्रकार से अशक्त प्रकारों के साथ फिर से उपयोग कर सकते हैं:
public static class TypeHelper
{
private static readonly HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(int), typeof(double), typeof(decimal),
typeof(long), typeof(short), typeof(sbyte),
typeof(byte), typeof(ulong), typeof(ushort),
typeof(uint), typeof(float)
};
public static bool IsNumeric(Type myType)
{
return NumericTypes.Contains(Nullable.GetUnderlyingType(myType) ?? myType);
}
}
फिलिप के प्रस्ताव के आधार पर दृष्टिकोण , SFun28 के आंतरिक प्रकार के Nullableप्रकारों के लिए बढ़ाया गया :
public static class IsNumericType
{
public static bool IsNumeric(this Type type)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
case TypeCode.Object:
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return Nullable.GetUnderlyingType(type).IsNumeric();
//return IsNumeric(Nullable.GetUnderlyingType(type));
}
return false;
default:
return false;
}
}
}
यही कारण है? मुझे यह जांचना था कि क्या दिया गया Type typeएक संख्यात्मक प्रकार है, और यदि कोई मनमाना object oसंख्यात्मक नहीं है।
C # 7 के साथ यह विधि मुझे स्विच केस की तुलना में बेहतर प्रदर्शन देती है TypeCodeऔर HashSet<Type>:
public static bool IsNumeric(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is float || o is double || o is decimal;
परीक्षण निम्नलिखित हैं:
public static class Extensions
{
public static HashSet<Type> NumericTypes = new HashSet<Type>()
{
typeof(byte), typeof(sbyte), typeof(ushort), typeof(uint), typeof(ulong), typeof(short), typeof(int), typeof(long), typeof(decimal), typeof(double), typeof(float)
};
public static bool IsNumeric1(this object o) => NumericTypes.Contains(o.GetType());
public static bool IsNumeric2(this object o) => o is byte || o is sbyte || o is ushort || o is uint || o is ulong || o is short || o is int || o is long || o is decimal || o is double || o is float;
public static bool IsNumeric3(this object o)
{
switch (o)
{
case Byte b:
case SByte sb:
case UInt16 u16:
case UInt32 u32:
case UInt64 u64:
case Int16 i16:
case Int32 i32:
case Int64 i64:
case Decimal m:
case Double d:
case Single f:
return true;
default:
return false;
}
}
public static bool IsNumeric4(this object o)
{
switch (Type.GetTypeCode(o.GetType()))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
}
class Program
{
static void Main(string[] args)
{
var count = 100000000;
//warm up calls
for (var i = 0; i < count; i++)
{
i.IsNumeric1();
}
for (var i = 0; i < count; i++)
{
i.IsNumeric2();
}
for (var i = 0; i < count; i++)
{
i.IsNumeric3();
}
for (var i = 0; i < count; i++)
{
i.IsNumeric4();
}
//Tests begin here
var sw = new Stopwatch();
sw.Restart();
for (var i = 0; i < count; i++)
{
i.IsNumeric1();
}
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (var i = 0; i < count; i++)
{
i.IsNumeric2();
}
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (var i = 0; i < count; i++)
{
i.IsNumeric3();
}
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
sw.Restart();
for (var i = 0; i < count; i++)
{
i.IsNumeric4();
}
sw.Stop();
Debug.WriteLine(sw.ElapsedMilliseconds);
}
आप इस्तेमाल कर सकते हैं Type.IsPrimitive और फिर बाहर प्रकार Booleanऔर Charप्रकार, कुछ इस तरह:
bool IsNumeric(Type type)
{
return type.IsPrimitive && type!=typeof(char) && type!=typeof(bool);
}
संपादित करें : यदि आप उन्हें संख्यात्मक नहीं मानते हैं, तो आप IntPtrऔर UIntPtrप्रकारों को भी अलग करना चाहते हैं ।
decimalप्रकार संख्यात्मक नहीं है?
नल-प्रकार समर्थन के साथ एक्सटेंशन टाइप करें।
public static bool IsNumeric(this Type type)
{
if (type == null) { return false; }
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = type.GetGenericArguments()[0];
}
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Single:
return true;
default:
return false;
}
}
संशोधित स्कीट की और arviman के समाधान का उपयोग Generics, Reflectionऔर C# v6.0।
private static readonly HashSet<Type> m_numTypes = new HashSet<Type>
{
typeof(int), typeof(double), typeof(decimal),
typeof(long), typeof(short), typeof(sbyte),
typeof(byte), typeof(ulong), typeof(ushort),
typeof(uint), typeof(float), typeof(BigInteger)
};
के बाद:
public static bool IsNumeric<T>( this T myType )
{
var IsNumeric = false;
if( myType != null )
{
IsNumeric = m_numTypes.Contains( myType.GetType() );
}
return IsNumeric;
}
के लिए उपयोग (T item):
if ( item.IsNumeric() ) {}
null झूठा लौटता है।
स्विच थोड़ा धीमा है, सबसे खराब स्थिति में हर बार तरीकों को शांत करना सभी प्रकार के माध्यम से जाना जाएगा। मुझे लगता है, डिक्टोनरी का उपयोग करना अधिक अच्छा है, इस स्थिति में आपके पास होगा O(1):
public static class TypeExtensions
{
private static readonly HashSet<Type> NumberTypes = new HashSet<Type>();
static TypeExtensions()
{
NumberTypes.Add(typeof(byte));
NumberTypes.Add(typeof(decimal));
NumberTypes.Add(typeof(double));
NumberTypes.Add(typeof(float));
NumberTypes.Add(typeof(int));
NumberTypes.Add(typeof(long));
NumberTypes.Add(typeof(sbyte));
NumberTypes.Add(typeof(short));
NumberTypes.Add(typeof(uint));
NumberTypes.Add(typeof(ulong));
NumberTypes.Add(typeof(ushort));
}
public static bool IsNumber(this Type type)
{
return NumberTypes.Contains(type);
}
}
C # के लिए TypeSupport नगेट पैकेज आज़माएं । इसमें सभी संख्यात्मक प्रकारों का पता लगाने के लिए समर्थन है (कई अन्य विशेषताओं के बीच):
var extendedType = typeof(int).GetExtendedType();
Assert.IsTrue(extendedType.IsNumericType);
दुर्भाग्य से इन प्रकारों में आम नहीं है, क्योंकि वे सभी मूल्य प्रकार हैं। लेकिन एक लंबे स्विच-केस से बचने के लिए आप इन सभी प्रकारों के साथ एक रीडायनली सूची को परिभाषित कर सकते हैं और फिर यह देख सकते हैं कि सूची में दिया गया प्रकार अंदर है या नहीं।
वे सभी मूल्य प्रकार (बूल और शायद एनम को छोड़कर) हैं। तो आप बस का उपयोग कर सकते हैं:
bool IsNumberic(object o)
{
return (o is System.ValueType && !(o is System.Boolean) && !(o is System.Enum))
}
struct... मुझे नहीं लगता कि आप यही चाहते हैं।
संपादित करें: ठीक है, मैंने नीचे दिए गए कोड को और अधिक प्रदर्शन करने के लिए संशोधित किया और फिर इसके खिलाफ @Hugo द्वारा पोस्ट किए गए परीक्षणों को चलाया। गति के बारे में है @ ह्यूगो IF के साथ अपने अनुक्रम में अंतिम आइटम का उपयोग कर (दशमलव)। यदि पहले आइटम 'बाइट' का उपयोग करते हुए उनका केक लिया जाता है, लेकिन प्रदर्शन के समय यह स्पष्ट रूप से आदेश देता है। हालांकि नीचे दिए गए कोड का उपयोग करना आसान है और इसकी लागत पर अधिक सुसंगत है, हालांकि, यह रखरखाव योग्य या भविष्य के प्रमाण-योग्य नहीं है।
देखने से लगता है कि Type.GetTypeCode () से Convert.GetTypeCode () में लगभग 25%, VS Enum.Parse () जो कि 10 गुना धीमा जैसा था, से स्विच होता है।
मुझे पता है कि यह पोस्ट पुरानी है लेकिन अगर टाइपकोड एनम विधि का उपयोग करना आसान है, (और शायद सबसे सस्ता) कुछ इस तरह होगा:
public static bool IsNumericType(this object o)
{
var t = (byte)Convert.GetTypeCode(o);
return t > 4 && t < 16;
}
TypeCode के लिए निम्नलिखित एनम परिभाषा को देखते हुए:
public enum TypeCode
{
Empty = 0,
Object = 1,
DBNull = 2,
Boolean = 3,
Char = 4,
SByte = 5,
Byte = 6,
Int16 = 7,
UInt16 = 8,
Int32 = 9,
UInt32 = 10,
Int64 = 11,
UInt64 = 12,
Single = 13,
Double = 14,
Decimal = 15,
DateTime = 16,
String = 18
}
मैंने इसका पूरी तरह से परीक्षण नहीं किया है, लेकिन मूल C # संख्यात्मक प्रकारों के लिए, यह इसे कवर करता प्रतीत होगा। हालाँकि, जैसा कि @JonSkeet ने उल्लेख किया है, यह enum सड़क पर .NET को जोड़ने के लिए अतिरिक्त प्रकारों के लिए अद्यतन नहीं है।
उफ़! सवाल गलत! व्यक्तिगत रूप से, स्कीट के साथ रोल करेगा ।
hrm, लगता है जैसे आप अपने डेटा DoSomethingपर करना चाहते हैं Type। आप जो कर सकते थे वह निम्नलिखित है
public class MyClass
{
private readonly Dictionary<Type, Func<SomeResult, object>> _map =
new Dictionary<Type, Func<SomeResult, object>> ();
public MyClass ()
{
_map.Add (typeof (int), o => return SomeTypeSafeMethod ((int)(o)));
}
public SomeResult DoSomething<T>(T numericValue)
{
Type valueType = typeof (T);
if (!_map.Contains (valueType))
{
throw new NotSupportedException (
string.Format (
"Does not support Type [{0}].", valueType.Name));
}
SomeResult result = _map[valueType] (numericValue);
return result;
}
}