Как использовать коммутационный футляр на Type?
Возможный дубликат:
Есть ли более эффективная альтернатива этому типу включения?
Мне нужно перебирать все свойства моего класса и проверять, есть ли его тип int, который я должен что-то сделать, если его строка... затем сделайте что-нибудь. Мне нужно это с помощью коммутационного футляра. Здесь я использую переключатель следующим образом, но он запрашивает некоторую константу. см. следующий код:
public static bool ValidateProperties(object o)
{
if(o !=null)
{
var sourceType = o.GetType();
var properties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Static);
foreach (var property in properties)
{
var type = property.GetType();
switch (type)
{
*case typeof(int):* getting error here
// d
}
}
}
}
Также я хочу знать, какую проверку следует использовать, typeof (int) или typeof (Int32)?
Ответы
Ответ 1
Вы не можете использовать блок переключателей для проверки значений типа Type
. Компиляция вашего кода должна дать вам сообщение об ошибке:
Выражение оператора switch или case должно быть bool, char, string, интеграл, перечисление или соответствующий нулевой тип
Вместо этого вам нужно использовать инструкции if
- else
.
Также: typeof(int)
и typeof(Int32)
эквивалентны. int
- это ключевое слово, а Int32
- имя типа.
UPDATE
Если вы ожидаете, что большинство типов будут внутренними, вы можете повысить производительность, используя блок переключателей с Type.GetTypeCode(...)
.
Например:
switch (Type.GetTypeCode(type))
{
case TypeCode.Int32:
// It an int
break;
case TypeCode.String:
// It a string
break;
// Other type code cases here...
default:
// Fallback to using if-else statements...
if (type == typeof(MyCoolType))
{
// ...
}
else if (type == typeof(MyOtherType))
{
// ...
} // etc...
}
Ответ 2
Хорошим и расширяемым способом сделать это является создание словаря типов и делегатов соответствующего типа на основе того, что вы хотите делать со значениями этого типа.
Например:
var typeProcessorMap = new Dictionary<Type, Delegate>
{
{ typeof(int), new Action<int>(i => { /* do something with i */ }) },
{ typeof(string), new Action<string>(s => { /* do something with s */ }) },
};
И затем:
void ValidateProperties(object o)
{
var t = o.GetType();
typeProcessorMap[t].DynamicInvoke(o); // invoke appropriate delegate
}
Это решение расширяемо, настраивается даже во время выполнения, и до тех пор, пока вы сохраняете ключи и типы значений делегата в typeProcessorMap
правильно подобранным, также безопасно.
Посмотрите на действие.
Ответ 3
Этот "ответ" - это проработка ответа Джона. (Маркировка CW)
Для записи DynamicInvoke
немного медленнее. Чтобы проиллюстрировать это, рассмотрим следующую программу:
void Main()
{
Func<int, string> myFunc = i => i.ToString();
myFunc.DynamicInvoke(1); // Invoke once so initial run costs are not considered
myFunc(1);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
for (int i = 0; i < 1000000; i++)
myFunc.DynamicInvoke(1);
stopwatch.Stop();
var elapsed = stopwatch.Elapsed;
stopwatch.Restart();
for (int i = 0; i < 1000000; i++)
myFunc(1);
stopwatch.Stop();
var elapsed2 = stopwatch.Elapsed;
Console.WriteLine("DynamicInvoke: " + elapsed);
Console.WriteLine("Direct Invocation: " + elapsed2);
}
Распечатывает:
DynamicInvoke: 00: 00: 03.1959900
Прямой вызов: 00: 00: 00.0735220
Это означает, что DynamicInvoke
(в этом простом случае) в 42 раза медленнее прямого вызова.
Ответ 4
Обычно самым простым решением является включение имени типа:
switch (type.Name)
{
case "Int32":
...
}