В соответствии с unmanaged
документацией ограничения:
Тип unmanaged
- это тип, который не является ссылочным типом и не содержит полей ссылочного типа ни при каких условиях.уровень вложенности.
Также в документации по проектированию языка C # упоминается ограничение неуправляемого типа :
Чтобы выполнить это ограничение, тип долженбыть структурой, и все поля типа должны относиться к одной из следующих категорий:
- Иметь тип
sbyte
, byte
, short
, ushort
, int
, uint
, long
, ulong
, char
, float
, double
, decimal
, bool
, IntPtr
или UIntPtr
. - быть любого типа
enum
. - быть типом указателя.
- быть определенной пользователем структуройкоторая удовлетворяет ограничению
unmanaged
.
Соображения
Обычно вызов MakeGenericType
является наиболее надежным решением для проверки универсального типаограничения, которые enfoпо CRL.Обычно пытаться выполнить проверку самостоятельно не очень хорошая идея, потому что может быть много правил, которые вы должны рассмотреть, и всегда есть шанс пропустить некоторые из них.Но имейте в виду, что, по крайней мере, во время написания этого ответа он не работает хорошо для ограничения unmanaged
.
.NET Core имеет RuntimeHelpers.IsReferenceOrContainsReferences
, но на момент написания этогоответ .NET Framework не имеет такой функции.Я должен отметить, что даже использование IsReferenceOrContainsReferences
не совсем надежно для этой задачи.
Например, смотрите проблему, которую я разместил здесь о двух структурах, у которых нет ссылочного типа, но одна из них оценивается как управляемая, одна из них неуправляемая (возможно, ошибка компилятора).
В любом случае, на данный момент, в зависимости от ваших предпочтений и требований, используйте одно из следующих решений, чтобы определить, какой тип может удовлетворить unmanaged
ограничение общего типа.
Вариант 1 - ИспользованиеMakeGenericType
В качестве опции, чтобы проверить, может ли тип удовлетворять ограничению unmanaged
, вы можете использовать следующий IsUnmanaged
метод расширения '.
Примечание: Он должен быть более надежным, но я должен сказать, что это не так.Кажется, для ограничения unmanaged
CLR не соблюдает ограничение и это просто функция компилятора C #.Поэтому, по крайней мере, на данный момент, я рекомендую использовать второй вариант.
using System;
using System.Reflection;
public static class UnmanagedTypeExtensions
{
class U<T> where T : unmanaged { }
public static bool IsUnManaged(this Type t)
{
try { typeof(U<>).MakeGenericType(t); return true; }
catch (Exception){ return false; }
}
}
Вариант 2. Написание собственного метода проверки документированных правил
В качестве другого варианта вы можете написать свой метод, проверяя документированные правила для ограничения unmanaged
.Следующий код содержит больше правил, чем других ответов, чтобы иметь возможность обрабатывать такие случаи, как int?
или (int,int)
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
public static class UnmanagedTypeExtensions
{
private static Dictionary<Type, bool> cachedTypes =
new Dictionary<Type, bool>();
public static bool IsUnManaged(this Type t)
{
var result = false;
if (cachedTypes.ContainsKey(t))
return cachedTypes[t];
else if (t.IsPrimitive || t.IsPointer || t.IsEnum)
result = true;
else if (t.IsGenericType || !t.IsValueType)
result = false;
else
result = t.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance)
.All(x => x.FieldType.IsUnManaged());
cachedTypes.Add(t, result);
return result;
}
}
Дополнительная информация
Вы можетеполезны следующие ссылки: