我想制作ToSigned,ToUnsinged的通用方法 这就是我所拥有的
public static class Number<T> {
// public static bool IsSigned = MinValue.Equals(0) ? false : true;
// public static bool IsUnsigned = MinValue.Equals(0) ? true : false;
public static object ToUnsigned(T input)
{
if (IsUnsigned)
return input;
// T is Signed
// How to derive unsigned type from signed type ?
// return SignedToUnsigned<T, unsigned T>(input);
return null;
}
public static object ToSigned(T input)
{
if (IsSigned)
return input;
// T is Unsigned
// How to derive signed type from unsigned type ?
// return UnsignedToSigned<T, signed T> (input);
return null;
}
}
我已经成功实现了SignedToUnsigned和UnsignedToSigned,但是如何从无符号类型派生签名类型,或从签名类型派生无符号类型?
答案 0 :(得分:0)
这没有内置机制;您必须根据comment.content.title
:
T
现在重复所有预期的类型。
请注意,这并不像它看起来那么昂贵,因为对于值类型if(typeof(T) == typeof(int)) return new Number<uint>(
(uint)((Number<int>)value).Value); // or similar
if(typeof(T) == typeof(long)) return new Number<ulong>(
(ulong)((Number<long>)value).Value); // or similar
,JIT每个T
发生一次,而JIT可以根据它删除分支常量包括T
。
我想知道,更好的选择是否是特定 typeof(T)
的扩展方法:
T
答案 1 :(得分:0)
内置无法做到这一点。
另请注意,Equals会检查它是否是相同的对象,而不是相同的值,因此(IsSigned,IsUnsigned)的结果是错误的。
您可以使用词典手动映射类型(或使用if语句,因为只有4种整数类型),然后使用反射调用您的方法:
但是如果你使用ifs和强制转换,并且在没有反射的情况下使用它,那么速度会明显加快。
public static class Number<T>
where T:System.IComparable
{
public static bool IsSigned = MinValue.CompareTo(default(T)) == 0 ? false : true;
public static bool IsUnsigned = MinValue.CompareTo(default(T)) == 0 ? true : false;
private static System.Collections.Generic.Dictionary<System.Type, System.Type> MapSignedUnsigned
= TypeMapSignedToUnsigned();
private static System.Collections.Generic.Dictionary<System.Type, System.Type> MapUnsignedSigned
= TypeMapUnsignedToSigned();
private static System.Collections.Generic.Dictionary<System.Type, System.Type>
TypeMapSignedToUnsigned()
{
System.Collections.Generic.Dictionary<System.Type, System.Type> dict
= new System.Collections.Generic.Dictionary<System.Type, System.Type>();
dict.Add(typeof(System.SByte), typeof(System.Byte));
dict.Add(typeof(System.Int16), typeof(System.UInt16));
dict.Add(typeof(System.Int32), typeof(System.UInt32));
dict.Add(typeof(System.Int64), typeof(System.UInt64));
return dict;
}
private static System.Collections.Generic.Dictionary<System.Type, System.Type>
TypeMapUnsignedToSigned()
{
System.Collections.Generic.Dictionary<System.Type, System.Type> dict
= new System.Collections.Generic.Dictionary<System.Type, System.Type>();
dict.Add(typeof(System.Byte), typeof(System.SByte));
dict.Add(typeof(System.UInt16), typeof(System.Int16));
dict.Add(typeof(System.UInt32), typeof(System.Int32));
dict.Add(typeof(System.UInt64), typeof(System.Int64));
return dict;
}
public static T2 ToUnsigned<T2>(T input)
{
if (IsUnsigned)
return (T2) (object) input;
// T is Signed
// t is unsigned type for T
System.Type t = MapSignedUnsigned[typeof(T)];
// TUnsigned SignedToUnsigned<TSigned, TUnsigned>(TSigned longValue)
// return SignedToUnsigned<T, t> (input);
System.Reflection.MethodInfo method = typeof(Number<T>).GetMethod("SignedToUnsigned");
System.Reflection.MethodInfo genericMethod = method.MakeGenericMethod(typeof(T), t);
return (T2) genericMethod.Invoke(null, new object[] { input });
}
public static T2 ToSigned<T2>(T input)
{
if (IsSigned)
return (T2) (object) input;
// T is Unsigned
// t is signed type for T
System.Type t = MapUnsignedSigned[typeof(T)];
// TSigned UnsignedToSigned<TUnsigned, TSigned>(TUnsigned ulongValue)
// return UnsignedToSigned<T, t> (input);
System.Reflection.MethodInfo method = typeof(Number<T>).GetMethod("UnsignedToSigned");
System.Reflection.MethodInfo genericMethod = method.MakeGenericMethod(typeof(T), t);
return (T2)genericMethod.Invoke(null, new object[] { input });
}
}
为什么不使用对象而不是泛型,例如:
public static class Number
{
private static object GetConstValue(System.Type t, string propertyName)
{
System.Reflection.FieldInfo pi = t.GetField(propertyName, System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
);
return pi.GetValue(null);
} // End Function GetConstValue
private static object GetMinValue(System.Type t)
{
return GetConstValue(t, "MinValue");
} // End Function GetMinValue
private static object GetMaxValue(System.Type t)
{
return GetConstValue(t, "MaxValue");
} // End Function GetMaxValue
private static object UnsignedToSigned(object value, System.Type t)
{
if (object.ReferenceEquals(t, typeof(System.UInt64)))
return UnsignedToSigned((System.UInt64)value);
else if (object.ReferenceEquals(t, typeof(System.UInt32)))
return UnsignedToSigned((System.UInt32)value);
else if (object.ReferenceEquals(t, typeof(System.UInt16)))
return UnsignedToSigned((System.UInt16)value);
else if (object.ReferenceEquals(t, typeof(System.Byte)))
return UnsignedToSigned((System.Byte)value);
throw new System.NotImplementedException($"UnsignedToSigned for type {t.Name} is not implemented.");
}
public static object UnsignedToSigned(object value)
{
if (value == null)
throw new System.ArgumentNullException(nameof(value), "Parameter cannot be NULL.");
System.Type t = value.GetType();
return UnsignedToSigned(value, t);
}
public static T UnsignedToSigned<T>(object value)
where T:System.IComparable
{
if (value == null)
throw new System.ArgumentNullException(nameof(value), "Parameter cannot be NULL.");
System.Type t = value.GetType();
System.Type tRet = typeof(T);
int sizeRet = System.Runtime.InteropServices.Marshal.SizeOf(tRet);
int sizeValue = System.Runtime.InteropServices.Marshal.SizeOf(t);
if (sizeRet != sizeValue)
{
throw new System.NotSupportedException($"Type mismatch: {tRet.Name} is not the matching signed type for {t.Name}");
}
System.IComparable minValue = (System.IComparable)GetMinValue(t);
System.IComparable minValueRet = (System.IComparable)GetMinValue(tRet);
if (minValueRet.CompareTo(System.Convert.ChangeType(0, tRet)) == 0)
{
throw new System.NotSupportedException($"Type mismatch: {tRet.Name} is not a signed type.");
}
// If we already have an signed type
// Type mismatch already prevented
if (minValue.CompareTo(System.Convert.ChangeType(0, t)) != 0)
{
return (T)value;
}
return (T)UnsignedToSigned(value, t);
}
private static object SignedToUnsigned(object value, System.Type t)
{
if (object.ReferenceEquals(t, typeof(System.Int64)))
return SignedToUnsigned((System.Int64)value);
else if (object.ReferenceEquals(t, typeof(System.Int32)))
return SignedToUnsigned((System.Int32)value);
else if (object.ReferenceEquals(t, typeof(System.Int16)))
return SignedToUnsigned((System.Int16)value);
else if (object.ReferenceEquals(t, typeof(System.SByte)))
return SignedToUnsigned((System.SByte)value);
throw new System.NotImplementedException("SignedToUnsigned for type " + t.FullName + " is not implemented.");
}
public static object SignedToUnsigned(object value)
{
if (value == null)
throw new System.ArgumentNullException(nameof(value), "Parameter cannot be NULL.");
System.Type t = value.GetType();
return SignedToUnsigned(value, t);
}
public static T SignedToUnsigned<T>(object value)
where T : System.IComparable
{
if (value == null)
throw new System.ArgumentNullException(nameof(value), "Parameter cannot be NULL.");
System.Type t = value.GetType();
System.Type tRet = typeof(T);
int sizeRet = System.Runtime.InteropServices.Marshal.SizeOf(tRet);
int sizeValue = System.Runtime.InteropServices.Marshal.SizeOf(t);
if (sizeRet != sizeValue)
{
throw new System.NotSupportedException($"Type mismatch: {tRet.Name} is not the matching unsigned type for {t.Name}");
}
System.IComparable minValue = (System.IComparable)GetMinValue(t);
System.IComparable minValueRet = (System.IComparable)GetMinValue(tRet);
if (minValueRet.CompareTo(System.Convert.ChangeType(0, tRet)) != 0)
{
throw new System.NotSupportedException($"Type mismatch: {tRet.Name} is not an unsigned type.");
}
// If we already have an unsigned type
// Type mismatch already prevented
if (minValue.CompareTo(System.Convert.ChangeType(0, t)) == 0)
{
return (T)value;
}
return (T)SignedToUnsigned(value, t);
}
private static System.Int64 UnsignedToSigned(System.UInt64 uintValue)
{
return unchecked((System.Int64)uintValue + System.Int64.MinValue);
}
private static System.UInt64 SignedToUnsigned(System.Int64 intValue)
{
return unchecked((System.UInt64)(intValue - System.Int64.MinValue));
}
private static System.Int32 UnsignedToSigned(System.UInt32 uintValue)
{
return unchecked((System.Int32)uintValue + System.Int32.MinValue);
}
private static System.UInt32 SignedToUnsigned(System.Int32 intValue)
{
return unchecked((System.UInt32)(intValue - System.Int32.MinValue));
}
private static System.Int16 UnsignedToSigned(System.UInt16 uintValue)
{
return (System.Int16) unchecked((System.Int16)uintValue + System.Int16.MinValue);
}
private static System.UInt16 SignedToUnsigned(System.Int16 intValue)
{
return unchecked((System.UInt16)(intValue - System.Int16.MinValue));
}
private static sbyte UnsignedToSigned(byte ulongValue)
{
return (sbyte) unchecked((sbyte)ulongValue + sbyte.MinValue);
}
private static byte SignedToUnsigned(sbyte longValue)
{
return unchecked((byte)(longValue - sbyte.MinValue));
}
}