Type 변수를 사용하여 변수 캐스팅
C #에서 object 유형의 변수를 T 유형의 변수로 캐스트 할 수 있습니까? T는 Type 변수에 정의되어 있습니까?
여기서 당신이 할 수있는 것은 간단한 (이것이 T 형 캐스트라고 가정) 캐스트이고 편리한 경우 (우리가 이것을 T로 변환 할 수 있다고 가정) :
public T CastExamp1<T>(object input) {
return (T) input;
}
public T ConvertExamp1<T>(object input) {
return (T) Convert.ChangeType(input, typeof(T));
}
편집하다:
의견의 일부 사람들은이 답변이 질문에 대답하지 않는다고 말합니다. 그러나이 라인 (T) Convert.ChangeType(input, typeof(T))
은 솔루션을 제공합니다. 이 Convert.ChangeType
메소드는 모든 오브젝트를 두 번째 인수로 제공된 유형으로 변환하려고 시도합니다.
예를 들면 다음과 같습니다.
Type intType = typeof(Int32);
object value1 = 1000.1;
// Variable value2 is now an int with a value of 1000
object value2a = Convert.ChangeType(value1, intType);
int value2b = Convert.ChangeType(value1, intType);
// Variable value3 is now an int with a value of 1000
dynamic value3 = Convert.ChangeType(value1, intType);
나는 당신이 캐스팅하려 할 때 매우 가능성이 코드 냄새의 서명 생각 때문에, 제네릭 답을 작성했습니다 a something
에 a something else
실제 유형을 처리하지 않고. 99.9 %의 시간이 필요하지 않은 적절한 인터페이스. 이해가 가까워 질 수있는 몇 가지 중요한 경우가있을 수 있지만 이러한 경우는 피하는 것이 좋습니다.
다른 답변에는 "동적"유형이 언급되어 있지 않습니다. 따라서 하나 이상의 답변을 추가하기 위해 "동적"유형을 사용하여 변환 된 객체를 정적 유형으로 캐스트하지 않고도 결과 객체를 저장할 수 있습니다.
dynamic changedObj = Convert.ChangeType(obj, typeVar);
changedObj.Method();
"동적"을 사용하면 컴파일러는 정적 유형 검사를 무시하므로주의하지 않으면 런타임 오류가 발생할 수 있습니다.
다음은 객체를 캐스팅하지만 일반 유형 변수가 아닌 System.Type
동적으로 캐스팅하는 방법입니다 .
System.Linq.Expressions
, type을 사용하여 런타임에 람다 식을 작성하여 Func<object, object>
입력을 개봉하고 원하는 유형 변환을 수행 한 다음 결과를 박스로 표시합니다. 캐스팅 된 모든 유형뿐만 아니라 언 캐스트 단계 때문에 캐스팅 된 유형에도 새로운 유형이 필요합니다. 이러한 표현식을 작성하는 것은 반영, 컴파일 및 동적 메소드 빌드로 인해 시간이 많이 소요됩니다. 운 좋게 일단 생성되면 표현식을 반복적으로 호출하고 높은 오버 헤드없이 호출 할 수 있으므로 각각을 캐시합니다.
private static Func<object, object> MakeCastDelegate(Type from, Type to)
{
var p = Expression.Parameter(typeof(object)); //do not inline
return Expression.Lambda<Func<object, object>>(
Expression.Convert(Expression.ConvertChecked(Expression.Convert(p, from), to), typeof(object)),
p).Compile();
}
private static readonly Dictionary<Tuple<Type, Type>, Func<object, object>> CastCache
= new Dictionary<Tuple<Type, Type>, Func<object, object>>();
public static Func<object, object> GetCastDelegate(Type from, Type to)
{
lock (CastCache)
{
var key = new Tuple<Type, Type>(from, to);
Func<object, object> cast_delegate;
if (!CastCache.TryGetValue(key, out cast_delegate))
{
cast_delegate = MakeCastDelegate(from, to);
CastCache.Add(key, cast_delegate);
}
return cast_delegate;
}
}
public static object Cast(Type t, object o)
{
return GetCastDelegate(o.GetType(), t).Invoke(o);
}
이것은 마술이 아닙니다. dynamic
키워드에서 와 마찬가지로 코드에서는 캐스팅이 발생하지 않으며 객체의 기본 데이터 만 변환됩니다. 컴파일 타임에 우리는 여전히 객체의 유형이 무엇인지 정확하게 파악 하여이 솔루션을 비실용적으로 만듭니다. 나는 이것을 임의의 유형으로 정의 된 변환 연산자를 호출하는 핵으로 썼다. 그러나 아마도 누군가 더 나은 사용 사례를 찾을 수있을 것이다.
단순함을 위해 박싱과 언 박싱을 제쳐두고 상속 계층 구조를 따라 캐스팅하는 것과 관련된 특정 런타임 작업은 없습니다. 대부분 컴파일 타임 일입니다. 기본적으로 캐스트는 변수 값을 다른 유형으로 처리하도록 컴파일러에 지시합니다.
캐스트 후 무엇을 할 수 있습니까? 타입을 모르기 때문에 어떤 메소드도 호출 할 수 없습니다. 당신이 할 수있는 특별한 일은 없을 것입니다. 특히 컴파일 타임에 가능한 유형을 알고 수동으로 캐스트하고 if
명령문을 사용 하여 각 케이스를 개별적으로 처리하는 경우에만 유용 합니다.
if (type == typeof(int)) {
int x = (int)obj;
DoSomethingWithInt(x);
} else if (type == typeof(string)) {
string s = (string)obj;
DoSomethingWithString(s);
} // ...
어떻게 그렇게 할 수 있습니까? 캐스트 후 오브젝트를 저장할 수있는 T 유형의 변수 또는 필드가 필요하지만 런타임시 T 만 알고있는 경우 어떻게 이러한 변수 또는 필드를 가질 수 있습니까? 따라서 불가능합니다.
Type type = GetSomeType();
Object @object = GetSomeObject();
??? xyz = @object.CastTo(type); // How would you declare the variable?
xyz.??? // What methods, properties, or fields are valid here?
Enum 유형으로 캐스팅 할 때 :
private static Enum GetEnum(Type type, int value)
{
if (type.IsEnum)
if (Enum.IsDefined(type, value))
{
return (Enum)Enum.ToObject(type, value);
}
return null;
}
그리고 당신은 그것을 다음과 같이 부를 것입니다 :
var enumValue = GetEnum(typeof(YourEnum), foo);
이것은 여러 enum 유형의 Description 속성 값을 int 값으로 얻는 경우에 필수적이었습니다.
public enum YourEnum
{
[Description("Desc1")]
Val1,
[Description("Desc2")]
Val2,
Val3,
}
public static string GetDescriptionFromEnum(Enum value, bool inherit)
{
Type type = value.GetType();
System.Reflection.MemberInfo[] memInfo = type.GetMember(value.ToString());
if (memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), inherit);
if (attrs.Length > 0)
return ((DescriptionAttribute)attrs[0]).Description;
}
return value.ToString();
}
그리고:
string description = GetDescriptionFromEnum(GetEnum(typeof(YourEnum), foo));
string description2 = GetDescriptionFromEnum(GetEnum(typeof(YourEnum2), foo2));
string description3 = GetDescriptionFromEnum(GetEnum(typeof(YourEnum3), foo3));
또는 (더 나은 접근 방식) 그러한 캐스팅은 다음과 같습니다.
private static T GetEnum<T>(int v) where T : struct, IConvertible
{
if (typeof(T).IsEnum)
if (Enum.IsDefined(typeof(T), v))
{
return (T)Enum.ToObject(typeof(T), v);
}
throw new ArgumentException(string.Format("{0} is not a valid value of {1}", v, typeof(T).Name));
}
Zyphrax의 답변을 사용할 때 "인터페이스는 IConvertible을 구현해야 함"예외를 피할 수없는 것을 발견 한 후 (인터페이스 구현 제외). 나는 약간의 비 전통적인 것을 시도하고 내 상황에서 일했습니다.
Newtonsoft.Json nuget 패키지 사용 ...
var castedObject = JsonConvert.DeserializeObject(JsonConvert.SerializeObject(myObject), myType);
public bool TryCast<T>(ref T t, object o)
{
if (
o == null
|| !typeof(T).IsAssignableFrom(o.GetType())
)
return false;
t = (T)o;
return true;
}
더 깨끗하게 :
public static bool TryCast<T>(ref T t, object o)
{
if (!(o is T))
{
return false;
}
t = (T)o;
return true;
}
대상 유형을 몰라도 런타임에 객체를 캐스트해야하는 경우 리플렉션을 사용하여 동적 변환기를 만들 수 있습니다.
이것은 캐싱 생성 방법없이 단순화 된 버전입니다.
public static class Tool
{
public static object CastTo<T>(object value) where T : class
{
return value as T;
}
private static readonly MethodInfo CastToInfo = typeof (Tool).GetMethod("CastTo");
public static object DynamicCast(object source, Type targetType)
{
return CastToInfo.MakeGenericMethod(new[] { targetType }).Invoke(null, new[] { source });
}
}
그런 다음 호출 할 수 있습니다.
var r = Tool.DynamicCast(myinstance, typeof (MyClass));
참고 URL : https://stackoverflow.com/questions/972636/casting-a-variable-using-a-type-variable
'Programing' 카테고리의 다른 글
HTTP 기본 인증-예상되는 브라우저 환경은 무엇입니까? (0) | 2020.04.07 |
---|---|
폴더를 선택하도록 OpenFileDialog를 어떻게 구성합니까? (0) | 2020.04.07 |
하나의 거대한 .css 파일과 여러 개의 작은 특정 .css 파일이 있습니까? (0) | 2020.04.07 |
maven pom.xml에서 사용되지 않는 종속성을 제거하는 간단한 방법이 있습니까? (0) | 2020.04.07 |
jQuery : jQuery에서 숨겨진 요소의 높이 가져 오기 (0) | 2020.04.07 |