简体   繁体   English

C#:如何在 object 期间使用隐式转换运算符进行类型转换?

[英]C#: How can I use implicit cast operator during object to type conversion?

HI!你好!

Here is my case: I have some value type which is wrapped into another type with appropriate implicit converters.这是我的情况:我有一些值类型,它使用适当的隐式转换器包装成另一种类型。 If I cast wrapped type to an object and then try to get original value I can do that in two-step cast only.如果我将包装类型转换为 object 然后尝试获得原始值,我只能在两步转换中做到这一点。 If simplified my code is as follows:如果简化我的代码如下:

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

First "Console.WriteLine" works OK.首先“Console.WriteLine”工作正常。 Second one fails.第二个失败。

Is there any way I can modify this behavior and get it working without double casting?有什么办法可以修改这种行为并让它在没有双重转换的情况下工作?

UPDATE 1更新 1

I must use object to value cast (in real application I have to cast ComboBox.SelectedItem property and I do not want to add extra property to ComboBox, because I'll have to change my UI interaction code everywhere).我必须使用 object 来进行值转换(在实际应用中,我必须转换 ComboBox.SelectedItem 属性,并且我不想在 ComboBox 中添加额外的属性,因为我必须在任何地方更改我的 UI 交互代码)。

UPDATE 2更新 2

Implicit conversions to and from System.Object are not allowed.不允许与 System.Object 进行隐式转换。

UPDATE 3更新 3

Updated my sample code to reflect the whole problem.更新了我的示例代码以反映整个问题。

Don't use object that way.不要那样使用object Write your first line like this instead:像这样写你的第一行:

Test res = new Test(1);

If you must have it in an object first, remember that all the compiler knows about it at this point is that it's an object, and nothing more.如果您必须首先将它放在 object 中,请记住,此时编译器所知道的只是它是 object,仅此而已。 You, as the programmer, have additional information about what you expect this object to be, but for the compiler to take advantage of that information you have to put it into your code somewhere.作为程序员,你有更多关于你期望这个 object 是什么的信息,但是为了让编译器利用这些信息,你必须把它放在你的代码中的某个地方。

Update:更新:
I'm glad I was able to find this again, because this almost-very-timely article by Eric Lippert, who works on the C# language design, went up this morning and explains the problem in depth:我很高兴我能再次找到这个,因为 Eric Lippert 的这篇几乎非常及时的文章,他从事 C# 语言设计,今天早上起来并深入解释了这个问题:
http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx http://blogs.msdn.com/ericlippert/archive/2009/03/19/representation-and-identity.aspx

If you want to simplify casting and not care performance effect, then create extension method.如果你想简化转换而不关心性能效果,那么创建扩展方法。

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

Usage用法

Console.WriteLine(res.To<MyEnum>());

Instead of adding implicit operators, consider implementing IConvertible .考虑实现IConvertible ,而不是添加隐式运算符。 You only need to implement the ToInt32 method, the others are meaningless and you can throw the InvalidCastException in the other methods.只需要实现 ToInt32 方法,其他没有意义,可以在其他方法中抛出 InvalidCastException。

After that, you can use Convert.ToInt32() method to convert your object in one step.之后,您可以使用Convert.ToInt32()方法一步转换您的 object。

or even甚至

var res = new Test(1);

Your local variable res is always of type object;您的局部变量 res 始终是 object 类型; so the line that isn't working is trying to convert an object, that isn't an int, to an int, which can't be done.所以不起作用的行是试图将不是 int 的 object 转换为无法完成的 int。 Same as this fails:与此失败相同:

        object d = 5.5d;
        Console.WriteLine((int)d);

EDIT:编辑:

Perhaps a pattern that might help is something like this:也许可能有帮助的模式是这样的:

        if (res.GetType() == typeof(Test))
        {
            Console.WriteLine((int)(Test)res);
        }
        else
        {
            Console.WriteLine((int)res);
        }

It's a very localized solution to your problem, but perhaps it will work for you.这是针对您的问题的非常本地化的解决方案,但也许它对您有用。

While the error is due to res being of type object, I would make the Test->int operator explicit...虽然错误是由于 res 的类型为 object,但我会让 Test->int 运算符显式...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM