HI!
这是我的情况:我有一些值类型,它包含在具有适当隐式转换器的另一种类型中。如果我将包装类型转换为对象然后尝试获取原始值,我只能在两步转换中执行此操作。 如果简化我的代码如下:
public enum MyEnum : int
{
First,
Second
}
public class Test<T>
{
public Test(T val)
{
Value = val;
}
private T Value { get; set; }
public static implicit operator T(Test<T> m)
{
return m.Value;
}
public static implicit operator Test<T>(T m)
{
var res = new Test<T>(m);
return res;
}
}
static void Main()
{
object res = new Test<MyEnum>(MyEnum.First);
Console.WriteLine((MyEnum)(Test<MyEnum>)res);
Console.WriteLine((MyEnum)res);
}
首先“Console.WriteLine”正常工作。第二个失败了。
有没有什么方法可以修改这种行为并让它在没有双重投射的情况下工作?
更新1
我必须使用object来进行值转换(在实际应用中我必须转换ComboBox.SelectedItem属性,我不想为ComboBox添加额外的属性,因为我必须在任何地方更改我的UI交互代码。)
更新2
不允许与System.Object进行隐式转换。
更新3
更新了我的示例代码以反映整个问题。
答案 0 :(得分:6)
请勿以此方式使用object
。写下你的第一行代替:
Test res = new Test(1);
如果你必须先在一个对象中拥有它,请记住所有编译器在此时都知道它是一个对象,仅此而已。作为程序员,您可以获得有关您希望此对象的其他信息,但是为了使编译器能够利用这些信息,您必须将其放入代码中。
<强>更新强>
我很高兴我能够再次找到这个,因为这篇关于C#语言设计的Eric Lippert几乎非常及时的文章今天早上起来并深入解释了这个问题:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx
答案 1 :(得分:4)
如果您想简化投射而不关心性能效果,请创建扩展方法。
public static T To<T>(this object obj) {
Type type = obj.GetType();
MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
MethodInfo method = methods.FirstOrDefault(mi => (mi.Name == "op_Implicit" || mi.Name == "op_Explicit") && mi.ReturnType == typeof(T));
if (method == null)
throw new ArgumentException();
return (T)method.Invoke(null, new[] { obj });
}
用法
Console.WriteLine(res.To<MyEnum>());
答案 2 :(得分:2)
不要添加隐式运算符,而应考虑实现IConvertible。您只需要实现ToInt32方法,其他方法毫无意义,您可以在其他方法中抛出InvalidCastException。
之后,您可以使用Convert.ToInt32()方法一步转换对象。
答案 3 :(得分:1)
甚至
var res = new Test(1);
答案 4 :(得分:1)
你的局部变量res总是类型为object;所以不工作的行试图将一个不是int的对象转换为int,这是无法完成的。与此相同失败:
object d = 5.5d;
Console.WriteLine((int)d);
编辑:
也许一种可能有用的模式是这样的:
if (res.GetType() == typeof(Test))
{
Console.WriteLine((int)(Test)res);
}
else
{
Console.WriteLine((int)res);
}
这是解决您问题的非常本地化的解决方案,但也许它适用于您。
答案 5 :(得分:0)
虽然错误是由于res属于object类型,但我会将Test-&gt; int运算符显式化...