C#显式运算符和对象
问题 请先看一下代码 这是我的自定义类:C#显式运算符和对象,c#,typeconverter,explicit-conversion,C#,Typeconverter,Explicit Conversion,问题 请先看一下代码 这是我的自定义类: public class float2D { public float X { get; private set; } public float Y { get; private set; } public float2D(float x, float y) { this.X = x; this.Y = y; } public static explicit operat
public class float2D
{
public float X { get; private set; }
public float Y { get; private set; }
public float2D(float x, float y)
{
this.X = x;
this.Y = y;
}
public static explicit operator Point(float2D x)
{
return new Point((int)x.X, (int)x.Y);
}
...
}
下面是我编写的测试代码:
private void TEST()
{
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = (Point)V; // Works
P = (Point)(V as object); // Specified cast is not valid.
}
如您所见,当值类型未知时,转换值失败。我相信这是因为它在对象类中搜索非实数类型的操作数。我怎样才能解决这个问题
我有一个代码,其中所有内容都是对象,它必须处理这些对话
如果你有什么想法,请告诉我
避免动态 好的,让我们以你能看到我到底想做什么和我的情况的方式来更改示例 以下是我的课程:
class TEST
{
dynamic OBJECT;
public void STORE<T>(ref T V)
{
this.OBJECT = V;
}
public T CONVERT<T>()
{
return (T)this.OBJECT;
}
}
类测试
{
动态对象;
公共空库(参考T V)
{
这个物体=V;
}
公共T CONVERT()
{
返回(T)this.OBJECT;
}
}
下面是测试代码:
float2D V = new float2D(1, 1);
TEST t = new TEST();
t.STORE(ref V);
Point P = t.CONVERT<Point>();
float2dv=新的float2D(1,1);
测试t=新测试();
t、 仓库(参考V);
点P=t.CONVERT();
有没有办法让dynamic从课堂上消失,让它继续工作?我真的想避免.Net4/4.5这是因为您正在将它强制转换为
对象,而您没有明确的强制转换,它不会隐式地假定您希望它成为浮动2D
是的,这两件事截然不同。第一行:
P = (Point)V; // Works
使用显式转换运算符,该运算符对于此组合是重载的。然而,第二个问题是:
P = (Point)(V as object); // Specified cast is not valid.
这将引用V
强制转换为对象
(我们通常都知道它是),然后分别从对象
强制转换为点
由于点
是一个结构
,因此它会尝试“取消装箱”相同的引用,就像它是一个装箱的点
。但是它不是一个装箱的点,因此错误是正确的。转换运算符不是多态的,仅当框包含相应类型的装箱副本时才允许取消装箱(注意:可以将枚举作为整数取消装箱,将整数取消装箱作为枚举-只要基础类型匹配)
但是,即使点
是一个类
,它仍然会失败,并出现类似的错误:如果类型不兼容,则保留引用的强制转换也不起作用。如其他答案所述,您不能这样做,因为您正试图将运行时强制转换应用于编译时转换操作
如果因为不想使用.NET 4.0的DLR而希望避免使用动态,则可以使用反射自己查找转换运算符。无法对执行此操作的特定应用程序的性能进行评论,但是:
public static TOutgoing Convert<TOutgoing>(object obj)
{
Type incomingType = obj.GetType();
MethodInfo conversionOperator = null;
foreach(var method in incomingType.GetMethods(BindingFlags.Static | BindingFlags.Public))
{
if (
method.Name == "op_Explicit" && //explicit converter
method.ReturnType == typeof(TOutgoing) && //returns your outgoing ("Point") type
method.GetParameters().Length == 1 && //only has 1 input parameter
method.GetParameters()[0].ParameterType == incomingType //parameter type matches your incoming ("float2D") type
)
{
conversionOperator = method;
break;
}
}
if (conversionOperator != null)
return (TOutgoing)conversionOperator.Invoke(null, new object[]{obj});
throw new Exception("No conversion operator found");
}
然后您的转换使用:
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = ConversionUtility.Convert<Point>(V); //passes
P = ConversionUtility.Convert<Point>((V as object)); //passes
float2dv=新的float2D(1,1);
点P=点。空;
P=转换利用率。转换(V)//通行证
P=ConversionUtility.Convert((V作为对象))//通行证
对于您的特定应用程序使用情况,不确定其中一个的性能优于另一个。第一个示例更加灵活,因为它在运行时执行检查,并且您不必预先注册您希望使用的转换。第二种可能更稳定,因为您只注册预期使用的转换,并且没有反射,只需强制转换和字典查找。寻找一个真正的过度工程化解决方案,该解决方案结合使用反射和他的记忆转换方法,以保持性能,同时也不需要调用conversion.RegisterConversion()
使用系统;
使用System.Collections.Generic;
使用System.Linq;
运用系统反思;
公共静态类ConvertUtil
{
///
///转换为类型
///使用反射确定适当的显式或隐式强制转换
///接线员。
///
///
///要转换为的类型。
///
///正在转换的对象。
///
///扮演。
///
///
///在运行时检测类型的类型。这是一个
///如果频繁使用,性能会受到轻微影响。
///
///
公共静态TResult ConvertTo(对象源),其中TResult:class
{
if(source==null | | sosurce是TResult)
{
返回源;
}
类型sourceType=source?.GetType();
return(TResult)GetConverter(sourceType,typeof(TResult))?.Invoke(source)??
抛出新的InvalidCastException($“没有来自类型的隐式或显式强制转换”+
$“{sourceType.Name}到{resultType.Name}存在。”);
}
///
///转换为类型
///使用反射确定适当的显式或隐式强制转换
///接线员。
///
///
///正在从转换类型。
///
///
///要转换的类型
///对。
///
///正在转换的对象。
///
///扮演。
///
///
///在编译时检测
///与使用时相比,性能略有提高
///经常。
///
///
公共静态TResult ConvertTo(TSource源)
where TSource:class
结果:在哪里上课
{
if(source==null | | sosurce是TResult)
{
返回源;
}
Func转换器=
GetConverter(typeof(TSource),typeof(TResult))??
抛出新的InvalidCastException($“没有来自的隐式或显式强制转换”+
$“存在类型{sourceType.Name}到{resultType.Name}”之间的连接。”);
返回(TResult)转换器(源);
}
///
///锁定线程安全。如果这不是一个问题,你可以删除这个和所有
///锁的部分
///
私有静态只读对象s_typeConvertersLock=新对象();
///
///从源类型到目标类型的映射及其转换
///功能。
///
普里夫
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = Convert<Point>(V); //passes
P = Convert<Point>((V as object)); //passes
public interface IConverter
{
object Convert(object incomingObject);
}
public class Converter<TIncoming, TOutgoing> : IConverter
{
private Func<TIncoming, TOutgoing> ConversionFunction;
public Converter(Func<TIncoming, TOutgoing> conversionFunction)
{
this.ConversionFunction = conversionFunction;
}
public object Convert(object incomingObject)
{
TIncoming typedIncomingObject = (TIncoming)incomingObject;
return ConversionFunction(typedIncomingObject);
}
}
public static class ConversionUtility
{
private static Dictionary<Type, Dictionary<Type, IConverter>> Converters = new Dictionary<Type, Dictionary<Type, IConverter>>();
public static void RegisterConversion<TIncoming, TOutgoing>(Func<TIncoming, TOutgoing> conversionFunction)
{
if (!Converters.ContainsKey(typeof(TIncoming)))
{
Converters[typeof(TIncoming)] = new Dictionary<Type, IConverter>();
}
Converters[typeof(TIncoming)].Add(typeof(TOutgoing), new Converter<TIncoming, TOutgoing>(conversionFunction));
}
public static TOutgoing Convert<TOutgoing>(object obj)
{
Type incomingType = obj.GetType();
IConverter converter = Converters[incomingType][typeof(TOutgoing)];
return (TOutgoing)converter.Convert(obj);
}
}
ConversionUtility.RegisterConversion((float2D obj) => (Point)obj);
float2D V = new float2D(1, 1);
Point P = Point.Empty;
P = ConversionUtility.Convert<Point>(V); //passes
P = ConversionUtility.Convert<Point>((V as object)); //passes