유형이 숫자인지 확인하는 방법
주어진 .Net 유형이 숫자인지 여부를 확인하는 방법이 있습니까? 예 : System.UInt32/UInt16/Double
모두 숫자입니다. .NET에서 긴 스위치 케이스를 피하고 싶습니다 Type.FullName
.
이 시도:
Type type = object.GetType();
bool isNumber = (type.IsPrimitiveImple && type != typeof(bool) && type != typeof(char));
기본 형식은 Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Char, Double 및 Single입니다.
촬영 기욤의 솔루션을 조금 더 :
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
스위치를 사용하지 말고 세트 만 사용하십시오.
HashSet<Type> NumericTypes = new HashSet<Type>
{
typeof(decimal), typeof(byte), typeof(sbyte),
typeof(short), typeof(ushort), ...
};
편집 : 유형 코드를 사용하는 것보다이 방법의 한 가지 장점은 새로운 숫자 유형이 .NET에 도입 될 때 (예 : BigInteger 및 Complex ) 조정하기 쉽다 는 것입니다. 반면 해당 유형 은 유형 코드를 얻지 못합니다 .
어떤 솔루션도 Nullable을 고려하지 않습니다.
Jon Skeet의 솔루션을 약간 수정했습니다.
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));
}
내 HashSet에 nullables 자체를 추가 할 수 있다는 것을 알고 있습니다. 그러나이 솔루션은 특정 Nullable을 목록에 추가하는 것을 잊어 버릴 위험을 방지합니다.
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;
}
}
제거 된 최적화에 대한 참고 사항 (엔지 주석 참조)
그리고 정말로 최적화하고 싶은 경우 (가독성 및 안전성 손실 ...) :
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;
}
기본적으로 Skeet의 솔루션이지만 다음과 같이 Nullable 유형과 함께 재사용 할 수 있습니다.
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의 내부 유형 검사 를 통해 강화 된 Philip의 제안 에 기반한 접근 방식 :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
.
Type.IsPrimitive를 사용 하고 다음 과 같이 Boolean
및 Char
유형 을 정렬 할 수 있습니다 .
bool IsNumeric(Type type)
{
return type.IsPrimitive && type!=typeof(char) && type!=typeof(bool);
}
편집 : 숫자로 간주하지 않으면 IntPtr
및 UIntPtr
유형도 제외하고 싶을 수 있습니다 .
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);
}
짧은 대답 : 아니요.
더 긴 답변 : 아니요.
사실 C #의 다양한 유형에는 숫자 데이터가 포함될 수 있습니다. 무엇을 예상해야하는지 (Int, Double 등) 모르는 경우 "long"case 문을 사용해야합니다.
이것도 작동 할 수 있습니다. 그러나 Type.Parse로 후속 작업을 수행하여 나중에 원하는 방식으로 캐스팅 할 수 있습니다.
public bool IsNumeric(object value)
{
float testValue;
return float.TryParse(value.ToString(), out testValue);
}
불행히도 이러한 유형은 모든 값 유형이라는 점 외에는 공통점이 많지 않습니다. 그러나 긴 전환 사례를 피하기 위해 이러한 모든 유형으로 읽기 전용 목록을 정의한 다음 주어진 유형이 목록 안에 있는지 확인하면됩니다.
모두 값 유형입니다 (boool 및 enum 제외). 따라서 다음을 간단히 사용할 수 있습니다.
bool IsNumberic(object o)
{
return (o is System.ValueType && !(o is System.Boolean) && !(o is System.Enum))
}
수정 스키트의 및 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
거짓을 반환합니다.
편집 : 글쎄, 나는 더 성능이 좋도록 아래 코드를 수정 한 다음 @Hugo가 게시 한 테스트를 실행했습니다. 속도는 시퀀스의 마지막 항목 (십진수)을 사용하는 @Hugo의 IF와 거의 비슷합니다. 그러나 첫 번째 항목 '바이트'를 사용하면 케이크를 가져 가지만 성능과 관련하여 분명히 순서가 중요합니다. 아래 코드를 사용하는 것이 작성하기 쉽고 비용면에서 더 일관 적이지만 유지 관리가 가능하거나 미래를 보장 할 수는 없습니다.
Looks like switching from Type.GetTypeCode() to Convert.GetTypeCode() sped up performance drastically, about 25%, VS Enum.Parse() which was like 10 times slower.
I know this post is old but IF using the TypeCode enum method, easiest (and probably the cheapest) would be something like this:
public static bool IsNumericType(this object o)
{
var t = (byte)Convert.GetTypeCode(o);
return t > 4 && t < 16;
}
Given the following enum definition for 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
}
I haven't tested it thoroughly, but for basic C# numeric types, this would seem to cover it. However, as @JonSkeet mentioned, this enum isn't updated for additional types added to .NET down the road.
Switch is a little slow, bacause every time methods in the worst situation will be go through all type. I think, using Dictonary is more nice, in this situation you will be have 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);
}
}
oops! Misread the question! Personally, would roll with Skeet's.
hrm, sounds like you want to DoSomething
on Type
of your data. What you could do is the following
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;
}
}
참고URL : https://stackoverflow.com/questions/1749966/c-sharp-how-to-determine-whether-a-type-is-a-number
'programing' 카테고리의 다른 글
요일의 정수 값을 얻는 방법 (0) | 2020.09.04 |
---|---|
CoreData : 경고 : 명명 된 클래스를로드 할 수 없습니다. (0) | 2020.09.04 |
Pandas DataFrame에서 True / False를 1/0에 매핑하려면 어떻게해야합니까? (0) | 2020.09.04 |
오류-데이터베이스가 사용 중이므로 독점 액세스를 얻을 수 없습니다. (0) | 2020.09.04 |
SourceTree에서 푸시를 시도 할 때 "태그가 이미 있기 때문에 업데이트가 거부되었습니다." (0) | 2020.09.04 |