代码之家  ›  专栏  ›  技术社区  ›  Nikolay R

C#:在对象到类型转换期间,如何使用隐式强制转换操作符?

  •  4
  • Nikolay R  · 技术社区  · 15 年前

    你好

    这里是我的例子:我有一个值类型,它通过适当的隐式转换器被包装成另一个类型。若我将包装类型转换为对象,然后尝试获取原始值,那个么我只能通过两步转换来实现。

    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);
        }
    

    有没有什么方法可以修改此行为并使其在不使用双重强制转换的情况下工作?

    我必须使用对象到值转换(在实际应用程序中,我必须转换ComboBox.SelectedItem属性,我不想向ComboBox添加额外属性,因为我必须在任何地方更改UI交互代码)。

    不允许与System.Object之间进行隐式转换。

    更新3

    更新了示例代码以反映整个问题。

    6 回复  |  直到 15 年前
        1
  •  6
  •   Joel Coehoorn    15 年前

    不要使用 object 那样。这样写你的第一行:

    Test res = new Test(1);
    

    如果必须先将其放入对象中,请记住 在这一点上,我们知道它是一个物体,仅此而已。作为程序员,您有关于您期望该对象是什么的附加信息,但是为了让编译器利用这些信息,您必须将其放在代码的某个地方。

    更新:
    我很高兴能再次找到这篇文章,因为从事C#语言设计的Eric Lippert撰写的这篇几乎非常及时的文章今天早上发表,深入解释了这个问题:
    http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx

        2
  •  4
  •   Chaowlert Chaisrichalermpol    15 年前

    若你们想简化铸造而不关心性能效果,那个么就创建扩展方法。

    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>());
    
        3
  •  2
  •   Dave Van den Eynde    15 年前

    代替添加隐式运算符,考虑实现 IConvertible . 您只需要实现ToInt32方法,其他方法没有意义,您可以在其他方法中抛出InvalidCastException。

    之后,您可以使用 Convert.ToInt32()

        4
  •  1
  •   Jhonny D. Cano -Leftware-    15 年前

    甚至

    var res = new Test(1);
    
        5
  •  1
  •   Timothy Carter    15 年前

    局部变量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);
            }
    

        6
  •  0
  •   Lee    15 年前

    虽然错误是由于res是object类型,但我会进行测试->整数运算符显式。。。