代码之家  ›  专栏  ›  技术社区  ›  Irfan Ul Haq

用户定义转换是如何在c#[closed]中发生的

  •  -1
  • Irfan Ul Haq  · 技术社区  · 11 年前

    有人能解释以下程序中用户定义转换是如何显式和隐式发生的吗?

    还请参阅我对显式转换方法和隐式转换方法的评论。

    /*** conversion.cs ***/
    
    using System;
    using System;
    
    struct RomanNumeral {
        public RomanNumeral(int value) {
            this.value=value; // what happen here?? 
        }
    
        static public implicit operator RomanNumeral(int value) {
            // here the default constructor is called  and the parameter in the 
            // argument is passed for the conversion to RomanNumeral but the 
            // constructor is of the type int so how it happen please explain?? 
            return new RomanNumeral(value); 
        }
    
        static public explicit operator int(RomanNumeral roman) {
            return roman.value;//how it is  happen here??
        }
    
        static public implicit operator string(RomanNumeral roman) {
            return ("Conversion not yet implemented");
        }
    
        private int value;
    }
    
    class Test {
        static public void Main() {
            RomanNumeral numeral;
    
            numeral=10;
    
    
            Console.WriteLine((int)numeral);
    
    
            Console.WriteLine(numeral);
    
    
            short s=(short)numeral;
    
            Console.WriteLine(s);
        }
    }
    
    2 回复  |  直到 11 年前
        1
  •  2
  •   Jon Skeet    11 年前

    让我们从这个例子开始:

    static public implicit operator RomanNumeral(int value)
    {
        // here the default constructor is called  and the argument is passed for
        // the conversion to RomanNumeral but the parameter in the constructor is
        // of the type int so how it happen please explain ??
        return new RomanNumeral(value);
    }
    

    为了便于阅读,我已经移动并重新格式化了您的评论。

    首先,不,默认构造函数是 调用(无论如何都是直接调用)。这个 RomanNumeral(int) 构造函数被调用。

    将隐式运算符看作是一个自动调用的方法是很有用的。想象一下,我们有一个这样的静态方法:

    // Note: body is the same as the implicit conversion
    public static RomanNumeral FromInt32(int value)
    {
        return new RomanNumeral(int value);
    }
    

    那么你可以这样想:

    int x = 10;
    RomanNumeral numeral = x;
    

    被编译为:

    int x = 10;
    RomanNumeral numeral = RomanNumeral.FromInt32(x);
    

    只是运算符是一个方法,它没有一个可以在C#中引用的名称。

        2
  •  0
  •   Ken Kin    11 年前
    /*** Answer with the comments in code ***/
    // You can imagine that conversion operator as `cast constructor`, though 
    // it can output an instance of target type in the ways other than a real 
    // constructor. 
    // The semantic model is `OutputType(InputType value)`
    // which means the LHS is of `OutputType` and RHS is of `InputType`. 
    // For more information, see 
    //      http://msdn.microsoft.com/en-us/library/85w54y0a.aspx
    struct RomanNumeral {
        public RomanNumeral(int value) {
            // here the parameter `value` assiged to the field value ----+
            this.value=value;                                         // |
        }                                                             // |
        //                                                               |
        static public implicit operator RomanNumeral(int value) {     // |
            // RomanNumeral(int value) is semantically tells that it     |
            // outputs a `RomanNumeral` from taking an `int` like        |
            // the constructor.                                          |
            // Thus if there was a method `M(RomanNumeral x)`            |
            // and called with M(3), then it's called with               |
            // M((RomanNumeral)3) by effection of this implicit operator |
            // and because it's implicit, you don't need to explicitly   |
            // cast it.                                                  |
            return new RomanNumeral(value);                           // |
        }                                                             // |
        //                                                               |
        static public explicit operator int(RomanNumeral roman) {     // |
            // Here the explicit operator just does the reverse thing    |
            // of what the implicit operator does                        |
            // However, because it's declared as explicit, you'll need   |
            // to tell the compiler you want to cast explicitly, or the  |
            // compiler treats statement like `int x=myRoman;` as an     |
            // error where `myRoman` is assumed a `RomanNumeral`         |
            // So you would write the statement as `int x=(int)myRoman;` |
            // and it compiles.                                          |
            return roman.value;                                       // |
        }                                                             // |
        //                                                               |
        static public implicit operator string(RomanNumeral roman) {  // |
            return ("Conversion not yet implemented");                // |
        }                                                             // |
        //                                                               |
        private int value; // <------------------------------------------+ 
    }