Программный эквивалент по умолчанию (Тип)

Я использую reflection, чтобы перебирать свойства Type и устанавливать определенные типы по умолчанию. Теперь я мог бы переключиться на тип и установить default(Type) по default(Type) явно, но я предпочел бы сделать это в одной строке. Существует ли программный эквивалент по умолчанию?

  • В случае типа значения используйте Activator.CreateInstance, и он должен работать нормально.
  • При использовании ссылочного типа просто возвращайте null
 public static object GetDefault(Type type) { if(type.IsValueType) { return Activator.CreateInstance(type); } return null; } 

В новой версии .net, например стандарте .net, type.IsValueType необходимо записать как type.GetTypeInfo().IsValueType

Почему бы не вызвать метод, который возвращает значение по умолчанию (T) с reflectionм? Вы можете использовать GetDefault любого типа с:

  public object GetDefault(Type t) { return this.GetType().GetMethod("GetDefaultGeneric").MakeGenericMethod(t).Invoke(this, null); } public T GetDefaultGeneric() { return default(T); } 

Вы можете использовать PropertyInfo.SetValue(obj, null) . Если вы вызовете тип значения, он даст вам значение по умолчанию. Это поведение описано в .NET 4.0 и .NET 4.5 .

Если вы используете .NET 4.0 или выше, и вам нужна программная версия, которая не является кодификацией правил, определенных вне кода , вы можете создать Expression , скомпилировать и запустить его на лету.

Следующий метод расширения примет Type и получит значение, возвращаемое по default(T) по методу Default в classе Expression :

 public static T GetDefaultValue() { // We want an Func which returns the default. // Create that expression here. Expression> e = Expression.Lambda>( // The default value, always get what the *code* tells us. Expression.Default(typeof(T)) ); // Compile and return the value. return e.Compile()(); } public static object GetDefaultValue(this Type type) { // Validate parameters. if (type == null) throw new ArgumentNullException("type"); // We want an Func which returns the default. // Create that expression here. Expression> e = Expression.Lambda>( // Have to convert to object. Expression.Convert( // The default value, always get what the *code* tells us. Expression.Default(type), typeof(object) ) ); // Compile and return the value. return e.Compile()(); } 

Вы также должны кэшировать вышеуказанное значение на основе Type , но помните, если вы вызываете это для большого количества экземпляров Type , и не используете его постоянно, память, потребляемая кешем, может перевесить преимущества.

Почему вы говорите, что дженерики не в порядке?

  public static object GetDefault(Type t) { Func f = GetDefault; return f.Method.GetGenericMethodDefinition().MakeGenericMethod(t).Invoke(null, null); } private static T GetDefault() { return default(T); } 

Это оптимизированное решение Flem:

 using System.Collections.Concurrent; namespace System { public static class TypeExtension { //a thread-safe way to hold default instances created at run-time private static ConcurrentDictionary typeDefaults = new ConcurrentDictionary(); public static object GetDefaultValue(this Type type) { return type.IsValueType ? typeDefaults.GetOrAdd(type, Activator.CreateInstance) : null; } } } 

Выбранный ответ является хорошим ответом, но будьте осторожны с возвращенным объектом.

 string test = null; string test2 = ""; if (test is string) Console.WriteLine("This will never be hit."); if (test2 is string) Console.WriteLine("Always hit."); 

Экстраполяция …

 string test = GetDefault(typeof(string)); if (test is string) Console.WriteLine("This will never be hit."); 

Выражения могут помочь здесь:

  private static Dictionary lambdasMap = new Dictionary(); private object GetTypedNull(Type type) { Delegate func; if (!lambdasMap.TryGetValue(type, out func)) { var body = Expression.Default(type); var lambda = Expression.Lambda(body); func = lambda.Compile(); lambdasMap[type] = func; } return func.DynamicInvoke(); } 

Я не тестировал этот fragment, но я думаю, что он должен производить «типизированные» нули для ссылочных типов.

Пока что нет ничего простого и элегантного, но у меня есть одна идея: если вы знаете тип свойства, которое хотите установить, вы можете написать свой собственный по default(T) . Существует два случая: T – тип значения, а T – ссылочный тип. Вы можете увидеть это, T.IsValueType . Если T является ссылочным типом, вы можете просто установить его в null . Если T – тип значения, тогда у него будет конструктор без параметров, который вы можете вызвать, чтобы получить «пустое» значение.

Я выполняю ту же задачу, как это.

 //in MessageHeader private void SetValuesDefault() { MessageHeader header = this; Framework.ObjectPropertyHelper.SetPropertiesToDefault(this); } //in ObjectPropertyHelper public static void SetPropertiesToDefault(T obj) { Type objectType = typeof(T); System.Reflection.PropertyInfo [] props = objectType.GetProperties(); foreach (System.Reflection.PropertyInfo property in props) { if (property.CanWrite) { string propertyName = property.Name; Type propertyType = property.PropertyType; object value = TypeHelper.DefaultForType(propertyType); property.SetValue(obj, value, null); } } } //in TypeHelper public static object DefaultForType(Type targetType) { return targetType.IsValueType ? Activator.CreateInstance(targetType) : null; } 

Эквивалентен ответу Дрора, но как метод расширения:

 namespace System { public static class TypeExtensions { public static object Default(this Type type) { object output = null; if (type.IsValueType) { output = Activator.CreateInstance(type); } return output; } } } 
  ///  /// returns the default value of a specified type ///  ///  public static object GetDefault(this Type type) { return type.IsValueType ? (!type.IsGenericType ? Activator.CreateInstance(type) : type.GenericTypeArguments[0].GetDefault() ) : null; } 
  • Каков пакет по умолчанию, в который помещаются мои classы, если я не укажу его?
  • Почему компилятор Scala запрещает перегруженные методы с аргументами по умолчанию?
  • Почему «final» не допускается в методах интерфейса Java 8?
  • Значение по умолчанию для типа в Runtime
  • Объявление примитивов / объектов, значения инициализации по умолчанию
  • Как заполнить / создать экземпляр массива C # с одним значением?
  • Принудительный клиент telnet в режиме символов
  • Переадресация по умолчанию для Error 404
  • Существует ли разумный подход к параметрам типа «по умолчанию» в C # Generics?
  • Почему компилятор не может вывести тип шаблона из аргументов по умолчанию?
  • Почему в параметрах C ++ последнее значение должно быть добавлено последними?
  • Interesting Posts

    Python time.clock () vs. time.time () точность?

    Невозможно ввести тильду в Mac OS X

    Нет двойной опции загрузки для Windows на моей машине

    Как удалить повторяющиеся записи из mysql db?

    Как рекурсивно найти последний измененный файл в каталоге?

    Регулярное выражение Lookbehind не работает с квантификаторами (‘+’ или ‘*’)

    Почему я должен применять методы по признаку, а не как часть этого признака?

    Как поместить изображение в div с помощью CSS?

    Windows 8.1 RTM BSOD с ошибкой «Критическое повреждение структуры»

    Серийный список JSON <KeyValuePair >

    Невозможно создать AVD или протестировать любое приложение с помощью AVD после создания инструментов сборки до 22.6

    Есть ли какой-либо прирост производительности при индексировании булевского поля?

    Как я могу сделать что-то вроде FlowLayout в Android?

    Воспроизведение звука с использованием примера soundpool

    Запуск программного обеспечения на Linux через Wine

    Давайте будем гением компьютера.