런타임시 유형의 기본값 [중복]
이 질문에는 이미 답변이 있습니다.
주어진 유형에 대해 기본값을 알고 싶습니다.
C #에는 이와 같은 작업을 수행하기위한 default라는 키워드가 있습니다.
object obj = default(Decimal);
하지만 Type 인스턴스 (myType이라고 함)가 있는데 이것을 말하면
object obj = default(myType);
작동하지 않습니다
이 작업을 수행하는 좋은 방법이 있습니까? 거대한 스위치 블록이 작동하지만 좋은 선택은 아니라는 것을 알고 있습니다.
null
참조 유형과 new myType()
값 유형 (int, float 등의 경우 0에 해당) 에는 실제로 두 가지 가능성이 있습니다. 따라서 실제로 두 가지 경우 만 고려하면됩니다.
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;
}
}
내 시스템 에서이 문제를 해결 한 다음 런타임에 임의 유형의 기본값을 올바르게 결정하는 방법이 있습니다.이 유형은 수천 가지 유형에 대해 테스트되었습니다.
/// <summary>
/// [ <c>public static object GetDefault(this Type type)</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <param name="type">The Type for which to get the default value</param>
/// <returns>The default value for <paramref name="type"/></returns>
/// <remarks>
/// 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.
/// </remarks>
/// <example>
/// To use this method in its native, non-extension form, make a call like:
/// <code>
/// object Default = DefaultValue.GetDefault(someType);
/// </code>
/// To use this method in its Type-extension form, make a call like:
/// <code>
/// object Default = someType.GetDefault();
/// </code>
/// </example>
/// <seealso cref="GetDefault<T>"/>
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 (i.e. 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 메서드는 정적 클래스 DefaultValue에서 구현됩니다. 다음과 같은 명령문으로이 메소드를 호출하십시오.
object Default = DefaultValue.GetDefault(someType);
GetDefault 메서드를 Type의 확장 메서드로 사용하려면 다음과 같이 호출하십시오.
object Default = someType.GetDefault();
이 두 번째 유형 확장 접근 방식은 호출에서 포함하는 DefaultValue 클래스 한정자를 참조 할 필요가 없기 때문에 더 간단한 클라이언트 코드 구문입니다.
위의 런타임 런타임 형식 인 GetDefault는 기본 C # 'default'키워드와 동일한 의미로 작동하며 동일한 결과를 생성합니다.
일반적인 형식의 GetDefault를 사용하려면 다음 기능에 액세스 할 수 있습니다.
/// <summary>
/// [ <c>public static T GetDefault< T >()</c> ]
/// <para></para>
/// Retrieves the default value for a given Type
/// </summary>
/// <typeparam name="T">The Type for which to get the default value</typeparam>
/// <returns>The default value for Type T</returns>
/// <remarks>
/// 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.
/// </remarks>
/// <seealso cref="GetDefault(Type)"/>
public static T GetDefault<T>()
{
return (T) GetDefault(typeof(T));
}
A call to the generic form could be something like:
int? inDefaultVal = DefaultValue.GetDefault<int?>();
Of course, the above generic form of GetDefault is unnecessary for C#, since it works the same as default(T). It is only useful for a .NET language that does not support the 'default' keyword but which supports generic types. In most cases, the generic form is unnecessary.
A useful corollary method is one to determine whether an object contains the default value for its Type. I also rely on the following IsObjectSetToDefault method for that purpose:
/// <summary>
/// [ <c>public static bool IsObjectSetToDefault(this Type ObjectType, object ObjectValue)</c> ]
/// <para></para>
/// Reports whether a value of type T (or a null reference of type T) contains the default value for that Type
/// </summary>
/// <remarks>
/// Reports whether the object is empty or unitialized for a reference type or nullable value type (i.e. is null) or
/// whether the object contains a default value for a non-nullable value type (i.e. int = 0, bool = false, etc.)
/// <para></para>
/// NOTE: For non-nullable value types, this method introduces a boxing/unboxing performance penalty.
/// </remarks>
/// <param name="ObjectType">Type of the object to test</param>
/// <param name="ObjectValue">The object value to test, or null for a reference Type or nullable value Type</param>
/// <returns>
/// true = The object contains the default value for its Type.
/// <para></para>
/// false = The object has been changed from its default value.
/// </returns>
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;
}
The above IsObjectSetToDefault
method can either be called in its native form or accessed as a Type-class extension.
How about something like...
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<T>
{
public static T GetDefault()
{
return default(T);
}
}
It produces the following output:
default(System.Object) =
default(System.String) =
default(System.Int32) = 0
default(System.Nullable`1[System.Int32]) =
What do you mean by "Default Value"? All reference Types ("class") have null as default value, while all value types will have their default values according to this table.
Here's a function that will return the default value for a nullable type (in other words, it returns 0 for both Decimal
and Decimal?
):
public static object DefaultValue(Type maybeNullable)
{
Type underlying = Nullable.GetUnderlyingType(maybeNullable);
if (underlying != null)
return Activator.CreateInstance(underlying);
return Activator.CreateInstance(maybeNullable);
}
참고URL : https://stackoverflow.com/questions/2490244/default-value-of-a-type-at-runtime
'IT' 카테고리의 다른 글
동일한 네트워크의 다른 컴퓨터에서이 로컬 호스트에 어떻게 연결합니까? (0) | 2020.06.13 |
---|---|
Windows : 명령 프롬프트에서 여러 줄 명령을 지정하는 방법? (0) | 2020.06.13 |
vim에서 특정 캐릭터로 점프하는 방법은 무엇입니까? (0) | 2020.06.13 |
원시 데이터에 std :: vector 포인터를 얻는 방법? (0) | 2020.06.13 |
pip를 사용하여 여러 파이썬 패키지를 한 번에 설치하는 방법 (0) | 2020.06.13 |