Значение по умолчанию для типа в Runtime

Для любого заданного типа я хочу знать его значение по умолчанию.

В C # для этого есть ключевое слово default

object obj = default(Decimal); 

но у меня есть экземпляр типа (называемый myType), и если я скажу это,

 object obj = default(myType); 

он не работает

Есть ли хороший способ сделать это? Я знаю, что огромный коммутационный блок будет работать, но это не очень хороший выбор.

Существует только две возможности: null для ссылочных типов и new myType() для типов значений (что соответствует 0 для int, float и т. Д.). Вам действительно нужно учитывать только два случая:

 object GetDefaultValue(Type t) { if (t.IsValueType) return Activator.CreateInstance(t); return null; } 

(Потому что типы значений всегда имеют конструктор по умолчанию, который вызывает Activator.CreateInstance никогда не сбой).

Вы также можете добавить его как метод расширения в System.Type:

 public static class TypeExtensions { public static object GetDefaultValue(this Type t) { if (t.IsValueType && Nullable.GetUnderlyingType(t) == null) return Activator.CreateInstance(t); else return null; } } 

Решив эту проблему в моих собственных системах, вот метод для правильного определения значения по умолчанию произвольного типа во время выполнения, которое было протестировано против тысяч типов:

  ///  /// [ public static object GetDefault(this Type type) ] ///  /// Retrieves the default value for a given Type ///  /// The Type for which to get the default value /// The default value for  ///  /// If a null Type, a reference Type, or a System.Void Type is supplied, this method always returns null. If a value type /// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an /// exception. ///  ///  /// To use this method in its native, non-extension form, make a call like: ///  /// object Default = DefaultValue.GetDefault(someType); ///  /// To use this method in its Type-extension form, make a call like: ///  /// object Default = someType.GetDefault(); ///  ///  ///  public static object GetDefault(this Type type) { // If no Type was supplied, if the Type was a reference type, or if the Type was a System.Void, return null if (type == null || !type.IsValueType || type == typeof(void)) return null; // If the supplied Type has generic parameters, its default value cannot be determined if (type.ContainsGenericParameters) throw new ArgumentException( "{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type + "> contains generic parameters, so the default value cannot be retrieved"); // If the Type is a primitive type, or if it is another publicly-visible value type (ie struct/enum), return a // default instance of the value type if (type.IsPrimitive || !type.IsNotPublic) { try { return Activator.CreateInstance(type); } catch (Exception e) { throw new ArgumentException( "{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe Activator.CreateInstance method could not " + "create a default instance of the supplied value type <" + type + "> (Inner Exception message: \"" + e.Message + "\")", e); } } // Fail with exception throw new ArgumentException("{" + MethodInfo.GetCurrentMethod() + "} Error:\n\nThe supplied value type <" + type + "> is not a publicly-visible type, so the default value cannot be retrieved"); } 

В этих примерах метод GetDefault реализуется в статическом classе DefaultValue. Вызовите этот метод с помощью инструкции, например:

  object Default = DefaultValue.GetDefault(someType); 

Чтобы использовать метод GetDefault в качестве метода расширения для типа, назовите его следующим образом:

  object Default = someType.GetDefault(); 

Второй подход, основанный на расширении типа, – это более простой синтаксис клиент-кода, поскольку он устраняет необходимость ссылки на содержащийся в classе classификатор classа DefaultValue.

Вышеупомянутая форма времени выполнения GetDefault работает с идентичной семантикой в ​​качестве примитивного ключевого слова C # по умолчанию и дает те же результаты.

Чтобы использовать общую форму GetDefault, вы можете получить доступ к следующей функции:

  ///  /// [ public static T GetDefault< T >() ] ///  /// Retrieves the default value for a given Type ///  /// The Type for which to get the default value /// The default value for Type T ///  /// If a reference Type or a System.Void Type is supplied, this method always returns null. If a value type /// is supplied which is not publicly visible or which contains generic parameters, this method will fail with an /// exception. ///  ///  public static T GetDefault() { return (T) GetDefault(typeof(T)); } 

Вызов общей формы может быть примерно таким:

  int? inDefaultVal = DefaultValue.GetDefault(); 

Конечно, вышеупомянутая общая форма GetDefault не нужна для C #, так как она работает так же, как и по умолчанию (T). Это полезно только для языка .NET, который не поддерживает ключевое слово default, но поддерживает общие типы. В большинстве случаев общая форма не нужна.

Полезным следственным методом является определение того, содержит ли объект значение по умолчанию для его Тип. Я также полагаюсь на следующий метод IsObjectSetToDefault для этой цели:

  ///  /// [ public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue) ] ///  /// Reports whether a value of type T (or a null reference of type T) contains the default value for that Type ///  ///  /// Reports whether the object is empty or unitialized for a reference type or nullable value type (ie is null) or /// whether the object contains a default value for a non-nullable value type (ie int = 0, bool = false, etc.) ///  /// NOTE: For non-nullable value types, this method introduces a boxing/unboxing performance penalty. ///  /// Type of the object to test /// The object value to test, or null for a reference Type or nullable value Type ///  /// true = The object contains the default value for its Type. ///  /// false = The object has been changed from its default value. ///  public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue) { // If no ObjectType was supplied, attempt to determine from ObjectValue if (ObjectType == null) { // If no ObjectValue was supplied, abort if (ObjectValue == null) { MethodBase currmethod = MethodInfo.GetCurrentMethod(); string ExceptionMsgPrefix = currmethod.DeclaringType + " {" + currmethod + "} Error:\n\n"; throw new ArgumentNullException(ExceptionMsgPrefix + "Cannot determine the ObjectType from a null Value"); } // Determine ObjectType from ObjectValue ObjectType = ObjectValue.GetType(); } // Get the default value of type ObjectType object Default = ObjectType.GetDefault(); // If a non-null ObjectValue was supplied, compare Value with its default value and return the result if (ObjectValue != null) return ObjectValue.Equals(Default); // Since a null ObjectValue was supplied, report whether its default value is null return Default == null; } 

Вышеуказанный метод IsObjectSetToDefault может быть вызван в его собственной форме или доступен как расширение типа.

Как насчет чего-то вроде …

 class Program { static void Main(string[] args) { PrintDefault(typeof(object)); PrintDefault(typeof(string)); PrintDefault(typeof(int)); PrintDefault(typeof(int?)); } private static void PrintDefault(Type type) { Console.WriteLine("default({0}) = {1}", type, DefaultGenerator.GetDefaultValue(type)); } } public class DefaultGenerator { public static object GetDefaultValue(Type parameter) { var defaultGeneratorType = typeof(DefaultGenerator<>).MakeGenericType(parameter); return defaultGeneratorType.InvokeMember( "GetDefault", BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod, null, null, new object[0]); } } public class DefaultGenerator { public static T GetDefault() { return default(T); } } 

Он производит следующий вывод:

 default(System.Object) = default(System.String) = default(System.Int32) = 0 default(System.Nullable`1[System.Int32]) = 

Что вы подразумеваете под «значением по умолчанию»? Все ссылочные типы («class») имеют значение null в качестве значения по умолчанию, а все типы значений будут иметь свои значения по умолчанию в соответствии с этой таблицей .

Вот функция, которая вернет значение по умолчанию для типа с нулевым значением (другими словами, оно возвращает 0 для Decimal и Decimal? ):

 public static object DefaultValue(Type maybeNullable) { Type underlying = Nullable.GetUnderlyingType(maybeNullable); if (underlying != null) return Activator.CreateInstance(underlying); return Activator.CreateInstance(maybeNullable); } 
  • Программный эквивалент по умолчанию (Тип)
  • Изменить статус по умолчанию Magento для дублированных продуктов
  • Поддерживает ли Java значения параметров по умолчанию?
  • Интерфейс с методами по умолчанию vs Абстрактный class в Java 8
  • Как загрузить пакеты в R автоматически?
  • Как открыть браузер по умолчанию в C #
  • Как вы используете конструктор, отличный от стандартного для члена?
  • Инициализация нормального массива с одним значением по умолчанию
  • Force R не использовать экспоненциальную нотацию (например, e + 10)?
  • Почему в параметрах C ++ последнее значение должно быть добавлено последними?
  • Таблицы стилей CSS по умолчанию для браузеров
  • Давайте будем гением компьютера.