#c# #reflection #.net-4.5
#.net #отражение
Вопрос:
Но вот пример:
Dim desiredType as Type
if IsNumeric(desiredType) then ...
РЕДАКТИРОВАТЬ: я знаю только тип, а не значение в виде строки.
Хорошо, к сожалению, мне приходится перебирать код типа.
Но это хороший способ сделать это:
if ((desiredType.IsArray))
return 0;
switch (Type.GetTypeCode(desiredType))
{
case 3:
case 6:
case 7:
case 9:
case 11:
case 13:
case 14:
case 15:
return 1;
}
;return 0;
Комментарии:
1. Здесь несколько лет спустя, но почему isArray имеет значение? Массив является объектом и должен отказать вашему коммутатору.
Ответ №1:
С опозданием на несколько лет, но вот мое решение (вы можете выбрать, включать ли логическое значение). Решает для случая с нулевым значением. Включен тест xUnit
/// <summary>
/// Determines if a type is numeric. Nullable numeric types are considered numeric.
/// </summary>
/// <remarks>
/// Boolean is not considered numeric.
/// </remarks>
public static bool IsNumericType( Type type )
{
if (type == null)
{
return false;
}
switch (Type.GetTypeCode(type))
{
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
case TypeCode.Object:
if ( type.IsGenericType amp;amp; type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
return IsNumericType(Nullable.GetUnderlyingType(type));
}
return false;
}
return false;
}
/// <summary>
/// Tests the IsNumericType method.
/// </summary>
[Fact]
public void IsNumericTypeTest()
{
// Non-numeric types
Assert.False(TypeHelper.IsNumericType(null));
Assert.False(TypeHelper.IsNumericType(typeof(object)));
Assert.False(TypeHelper.IsNumericType(typeof(DBNull)));
Assert.False(TypeHelper.IsNumericType(typeof(bool)));
Assert.False(TypeHelper.IsNumericType(typeof(char)));
Assert.False(TypeHelper.IsNumericType(typeof(DateTime)));
Assert.False(TypeHelper.IsNumericType(typeof(string)));
// Arrays of numeric and non-numeric types
Assert.False(TypeHelper.IsNumericType(typeof(object[])));
Assert.False(TypeHelper.IsNumericType(typeof(DBNull[])));
Assert.False(TypeHelper.IsNumericType(typeof(bool[])));
Assert.False(TypeHelper.IsNumericType(typeof(char[])));
Assert.False(TypeHelper.IsNumericType(typeof(DateTime[])));
Assert.False(TypeHelper.IsNumericType(typeof(string[])));
Assert.False(TypeHelper.IsNumericType(typeof(byte[])));
Assert.False(TypeHelper.IsNumericType(typeof(decimal[])));
Assert.False(TypeHelper.IsNumericType(typeof(double[])));
Assert.False(TypeHelper.IsNumericType(typeof(short[])));
Assert.False(TypeHelper.IsNumericType(typeof(int[])));
Assert.False(TypeHelper.IsNumericType(typeof(long[])));
Assert.False(TypeHelper.IsNumericType(typeof(sbyte[])));
Assert.False(TypeHelper.IsNumericType(typeof(float[])));
Assert.False(TypeHelper.IsNumericType(typeof(ushort[])));
Assert.False(TypeHelper.IsNumericType(typeof(uint[])));
Assert.False(TypeHelper.IsNumericType(typeof(ulong[])));
// numeric types
Assert.True(TypeHelper.IsNumericType(typeof(byte)));
Assert.True(TypeHelper.IsNumericType(typeof(decimal)));
Assert.True(TypeHelper.IsNumericType(typeof(double)));
Assert.True(TypeHelper.IsNumericType(typeof(short)));
Assert.True(TypeHelper.IsNumericType(typeof(int)));
Assert.True(TypeHelper.IsNumericType(typeof(long)));
Assert.True(TypeHelper.IsNumericType(typeof(sbyte)));
Assert.True(TypeHelper.IsNumericType(typeof(float)));
Assert.True(TypeHelper.IsNumericType(typeof(ushort)));
Assert.True(TypeHelper.IsNumericType(typeof(uint)));
Assert.True(TypeHelper.IsNumericType(typeof(ulong)));
// Nullable non-numeric types
Assert.False(TypeHelper.IsNumericType(typeof(bool?)));
Assert.False(TypeHelper.IsNumericType(typeof(char?)));
Assert.False(TypeHelper.IsNumericType(typeof(DateTime?)));
// Nullable numeric types
Assert.True(TypeHelper.IsNumericType(typeof(byte?)));
Assert.True(TypeHelper.IsNumericType(typeof(decimal?)));
Assert.True(TypeHelper.IsNumericType(typeof(double?)));
Assert.True(TypeHelper.IsNumericType(typeof(short?)));
Assert.True(TypeHelper.IsNumericType(typeof(int?)));
Assert.True(TypeHelper.IsNumericType(typeof(long?)));
Assert.True(TypeHelper.IsNumericType(typeof(sbyte?)));
Assert.True(TypeHelper.IsNumericType(typeof(float?)));
Assert.True(TypeHelper.IsNumericType(typeof(ushort?)));
Assert.True(TypeHelper.IsNumericType(typeof(uint?)));
Assert.True(TypeHelper.IsNumericType(typeof(ulong?)));
// Testing with GetType because of handling with non-numerics. See:
// http://msdn.microsoft.com/en-us/library/ms366789.aspx
// Using GetType - non-numeric
Assert.False(TypeHelper.IsNumericType((new object()).GetType()));
Assert.False(TypeHelper.IsNumericType(DBNull.Value.GetType()));
Assert.False(TypeHelper.IsNumericType(true.GetType()));
Assert.False(TypeHelper.IsNumericType('a'.GetType()));
Assert.False(TypeHelper.IsNumericType((new DateTime(2009, 1, 1)).GetType()));
Assert.False(TypeHelper.IsNumericType(string.Empty.GetType()));
// Using GetType - numeric types
// ReSharper disable RedundantCast
Assert.True(TypeHelper.IsNumericType((new byte()).GetType()));
Assert.True(TypeHelper.IsNumericType(43.2m.GetType()));
Assert.True(TypeHelper.IsNumericType(43.2d.GetType()));
Assert.True(TypeHelper.IsNumericType(((short)2).GetType()));
Assert.True(TypeHelper.IsNumericType(((int)2).GetType()));
Assert.True(TypeHelper.IsNumericType(((long)2).GetType()));
Assert.True(TypeHelper.IsNumericType(((sbyte)2).GetType()));
Assert.True(TypeHelper.IsNumericType(2f.GetType()));
Assert.True(TypeHelper.IsNumericType(((ushort)2).GetType()));
Assert.True(TypeHelper.IsNumericType(((uint)2).GetType()));
Assert.True(TypeHelper.IsNumericType(((ulong)2).GetType()));
// ReSharper restore RedundantCast
// Using GetType - nullable non-numeric types
bool? nullableBool = true;
Assert.False(TypeHelper.IsNumericType(nullableBool.GetType()));
char? nullableChar = ' ';
Assert.False(TypeHelper.IsNumericType(nullableChar.GetType()));
DateTime? nullableDateTime = new DateTime(2009, 1, 1);
Assert.False(TypeHelper.IsNumericType(nullableDateTime.GetType()));
// Using GetType - nullable numeric types
byte? nullableByte = 12;
Assert.True(TypeHelper.IsNumericType(nullableByte.GetType()));
decimal? nullableDecimal = 12.2m;
Assert.True(TypeHelper.IsNumericType(nullableDecimal.GetType()));
double? nullableDouble = 12.32;
Assert.True(TypeHelper.IsNumericType(nullableDouble.GetType()));
short? nullableInt16 = 12;
Assert.True(TypeHelper.IsNumericType(nullableInt16.GetType()));
short? nullableInt32 = 12;
Assert.True(TypeHelper.IsNumericType(nullableInt32.GetType()));
short? nullableInt64 = 12;
Assert.True(TypeHelper.IsNumericType(nullableInt64.GetType()));
sbyte? nullableSByte = 12;
Assert.True(TypeHelper.IsNumericType(nullableSByte.GetType()));
float? nullableSingle = 3.2f;
Assert.True(TypeHelper.IsNumericType(nullableSingle.GetType()));
ushort? nullableUInt16 = 12;
Assert.True(TypeHelper.IsNumericType(nullableUInt16.GetType()));
ushort? nullableUInt32 = 12;
Assert.True(TypeHelper.IsNumericType(nullableUInt32.GetType()));
ushort? nullableUInt64 = 12;
Assert.True(TypeHelper.IsNumericType(nullableUInt64.GetType()));
}
Комментарии:
1. Чтобы добавить к этому могильному, если вы собираетесь определить IsNumericType для получения типа, почему бы не рекурсивно передать результат Nullable . Получить underlyingtype к той же функции и вернуть ее значение?
2. да … отличное предложение. так более элегантно. обновленный пост.
3. почему бы не объявить этот метод в статическом классе и сделать его доступным для ввода:
public static bool IsNumeric(this Type type) { /*...*/ }
?4. Хорошее решение, а также 1 для тестов. Определенно лучше, чем принятый ответ.
5. Хорошее решение, просто имейте в виду, что перечисление будет классифицироваться как целое число, используя приведенную выше логику
Ответ №2:
Вы можете узнать, является ли переменная числовой, используя Type.GetTypeCode()
метод:
TypeCode typeCode = Type.GetTypeCode(desiredType);
if (typeCode == TypeCode.Double || typeCode == TypeCode.Integer || ...)
return true;
Вам нужно будет заполнить все доступные числовые типы в части «…» 😉
Подробнее здесь: перечисление кода типа
Комментарии:
1. Я надеялся, что мне не придется проверять каждый тип, но это работает, спасибо!
2. К вашему сведению, этот код не будет работать, если они являются типами с нулевым значением. В этом случае код типа возвращается как объект. Все еще пытаюсь выяснить, как обойти это. Кто-нибудь?
3. Лучше: Foreach (TypeCode typecode в new TypeCode[] { TypeCode . Double […] } если typecode == Type . GetTypeCode(desiredType) возвращает true; возвращает false;
4. почему вы, ребята, не могли просто сделать это для нас, чтобы мы могли копировать / вставлять?
5. @Ben, ты можешь сделать «if (1 is int)» в C #, а не «if (1.GetType() is int)». Надеюсь, вы поняли идею.
Ответ №3:
Отличная статья здесь исследует IsNumeric для C #.
Вариант 1:
Ссылка Microsoft.VisualBasic.dll , затем выполните следующие действия:
if (Microsoft.VisualBasic.Information.IsNumeric("5"))
{
//Do Something
}
Вариант 2:
public static bool Isumeric (object Expression)
{
bool f;
ufloat64 a;
long l;
IConvertible iConvertible = null;
if ( ((Expression is IConvertible)))
{
iConvertible = (IConvertible) Expression;
}
if (iConvertible == null)
{
if ( ((Expression is char[])))
{
Expression = new String ((char[]) Expression);
goto IL_002d; // hopefully inserted by optimizer
}
return 0;
}
IL_002d:
TypeCode typeCode = iConvertible.GetTypeCode ();
if ((typeCode == 18) || (typeCode == 4))
{
string str = iConvertible.ToString (null);
try
{
if ( (StringType.IsHexOrOctValue (str, l)))
{
f = true;
return f;
}
}
catch (Exception )
{
f = false;
return f;
};
return DoubleType.TryParse (str, a);
}
return Utils.IsNumericTypeCode (typeCode);
}
internal static bool IsNumericType (Type typ)
{
bool f;
TypeCode typeCode;
if ( (typ.IsArray))
{
return 0;
}
switch (Type.GetTypeCode (typ))
{
case 3:
case 6:
case 7:
case 9:
case 11:
case 13:
case 14:
case 15:
return 1;
};
return 0;
}
Ответ №4:
Если у вас есть ссылка на реальный объект, вот простое решение для C #, которое очень просто:
/// <summary>
/// Determines whether the supplied object is a .NET numeric system type
/// </summary>
/// <param name="val">The object to test</param>
/// <returns>true=Is numeric; false=Not numeric</returns>
public static bool IsNumeric(ref object val)
{
if (val == null)
return false;
// Test for numeric type, returning true if match
if
(
val is double || val is float || val is int || val is long || val is decimal ||
val is short || val is uint || val is ushort || val is ulong || val is byte ||
val is sbyte
)
return true;
// Not numeric
return false;
}
Комментарии:
1. Я придумал нечто подобное. Могу ли я спросить, почему вы используете ключевое слово «ref» с аргументом val.
2. На самом деле это то же самое, что и решения на основе кода типа, описанные выше, за исключением того, что они медленнее…
Ответ №5:
Отдавая должное @SFun28 и @nawfal (спасибо!), Я использовал оба их ответа, немного изменил и придумал эти методы расширения:
public static class ReflectionExtensions
{
public static bool IsNullable(this Type type) {
return
type != null amp;amp;
type.IsGenericType amp;amp;
type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
public static bool IsNumeric(this Type type) {
if (type == null || type.IsEnum)
return false;
if (IsNullable(type))
return IsNumeric(Nullable.GetUnderlyingType(type));
switch (Type.GetTypeCode(type)) {
case TypeCode.Byte:
case TypeCode.Decimal:
case TypeCode.Double:
case TypeCode.Int16:
case TypeCode.Int32:
case TypeCode.Int64:
case TypeCode.SByte:
case TypeCode.Single:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
return true;
default:
return false;
}
}
}
Комментарии:
1. не понимаю, почему if ‘тип. IsEnum’ возвращает false?
2. @Riga Я мог видеть, что перечисления являются серой областью, но я бы ошибся в сторону false . Допустим, вы создаете сериализатор JSON и хотите, чтобы перечисления были сериализованы в строки. В этом случае вы не хотели бы рассматривать их как число.
Ответ №6:
Я знаю, что это ОЧЕНЬ поздний ответ, но вот функция, которую я использую:
public static bool IsNumeric(Type type)
{
var t = Nullable.GetUnderlyingType(type) ?? type;
return t.IsPrimitive || t == typeof(decimal);
}
Если вы хотите исключить char
как числовой тип, вы можете использовать этот пример:
return (t.IsPrimitive || t == typeof(decimal)) amp;amp; t != typeof(char);
Примитивными типами являются Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double и Single.
Примечание: Эта проверка включает IntPtr и UIntPtr .
Вот та же функция, что и общий метод расширения (я знаю, что это не работает для случая OP, но кто-то другой может счесть это полезным):
public static bool IsNumeric<T>(this T value)
{
var t = Nullable.GetUnderlyingType(value.GetType()) ?? value.GetType();
return t.IsPrimitive || t == typeof(decimal);
}
Ответ №7:
Вот как MS реализовала это, в System.Dynamic.Utils.TypeUtils
котором это внутренний класс. Оказывается, что они не считают System.Decimal
числовой тип ( Decimal
опущен в перечислении). И, что интересно, MS находит System.Char
тип числовым. В противном случае это точно так же, как ответ SFun28. Я полагаю, что его ответ «более правильный».
internal static bool IsNumeric(Type type)
{
type = type.GetNonNullableType();
if (!type.IsEnum)
{
switch (Type.GetTypeCode(type))
{
case TypeCode.Char:
case TypeCode.SByte:
case TypeCode.Byte:
case TypeCode.Int16:
case TypeCode.UInt16:
case TypeCode.Int32:
case TypeCode.UInt32:
case TypeCode.Int64:
case TypeCode.UInt64:
case TypeCode.Single:
case TypeCode.Double:
return true;
}
}
return false;
}
//where GetNonNullableType is defined as
internal static Type GetNonNullableType(this Type type)
{
if (type.IsNullableType())
{
return type.GetGenericArguments()[0];
}
return type;
}
//where IsNullableType is defined as
internal static bool IsNullableType(this Type type)
{
return type.IsGenericType amp;amp; type.GetGenericTypeDefinition() == typeof(Nullable<>);
}
Комментарии:
1. Интересно, есть ли способ еще больше оптимизировать это, используя побитовые операции и еще много чего…
Ответ №8:
''// Return true if a type is a numeric type.
Private Function IsNumericType(ByVal this As Type) As Boolean
''// All the numeric types have bits 11xx set whereas non numeric do not.
''// That is if you include char type which is 4(decimal) = 100(binary).
If this.IsArray Then Return False
If (Type.GetTypeCode(this) And amp;HC) > 0 Then Return True
Return False
End Function
Комментарии:
1. Совершенно неверно, SByte является числовым и имеет идентификатор 5, который равен ‘0101’, так что это неправильно.
Ответ №9:
Теперь вы можете использовать метод .NET Framework
typeof(decimal?).IsNumericType()
Ответ №10:
Используйте тип.IsValueType() и TryParse():
public bool IsInteger(Type t)
{
int i;
return t.IsValueType amp;amp; int.TryParse(t.ToString(), out i);
}
Комментарии:
1. «t» не является переменной рассматриваемого типа. Это тип, о котором идет речь. t никогда не будет числом в этом коде.