locked
Conversion rules for method parameters using literal arguments RRS feed

  • Question

  •  

    I am confused about something. Of course I am, or I wouldn't be writing this!

     

    I am reading a book that helps Java developers transition to C#, and the topic I am befuddled about is implicit and explicit conversion using literals.

     

    I’ll try to make this as succinct as possible.

     

    The book makes these seemingly contradictory statements:

     

    … an explicit cast is required when you pass the literal to a method parameter.

     

    Then later in the book is this statement:

     

    The implicit rules stated for each of the data types are used at the time the assignment is made and parameters are passed to a method call.

     

    So what does C# do vis-à-vis conversion during a method call?

     

    I decided to try it with the following code:

     

    Test.cs:


     

    using People;  
    using System;  
     
    public class Test {  
      public static void Main(string[] args) {  
        Developer d = new Developer();  
        d.MyMethod(101);  
        Console.ReadLine();  
         
      }  
    }  
     

    People.cs:

    using System;  
    namespace People {  
      public class Developer {  
        public void Fears (Object o) {  
          Console.WriteLine("A developer fears "+o);  
        }  
            public void MyMethod(sbyte num) {  
                Console.WriteLine(num);  
                Console.WriteLine("Ran sbyte method");  
            }  
              
       }  
        
      }  
     

    As is, this code compiled and ran fine with an integer literal passed to an sbyte parameter.

    Also, assigning an integer literal to an sbyte variable gave no errors.

     

    Now read this statement from the book:

     

    …suppose you have a method that takes an sbyte. When this method is passed an integer literal, the literal will have to be cast to sbyte. Explicit casting is also required when a larger data type is being assigned to a smaller data type.

     

    So, not only does it say it has to be cast, but it has to be explicit. But I didn’t use any explicit conversions!

     

    This isn't technically data truncation since it still has to be in the range of an sbyte. But my understanding of integer literals is that they are either int, uint, long, or ulong.

    The book says valid implicit conversions for an integer are long, float, double, or decimal. There is no implicit conversion rule for integers to sbytes, bytes, etc.

     

    What kind of legerdemain is going on here?

    • Edited by landgazr Thursday, November 13, 2008 7:30 PM
    Thursday, November 13, 2008 7:26 PM

Answers

  • The compiler is inferring the type of 101 as being sbyte, not int.  Technically, it's never a conversion.

    If the value you place there cannot be inferred to be an sbyte (either it's a variable of some other type, or it's out of range for the type specified by the parameter declaration in the method head), then you'll get a compile error.
    David Morton - http://blog.davemorton.net/
    • Marked as answer by landgazr Thursday, November 13, 2008 10:51 PM
    Thursday, November 13, 2008 9:11 PM
    Moderator

All replies

  • In the situation you posed above, the compiler is inferring the type of "101" from the method call.  In fact, if you try the same thing, but try passing in, say, 550, you'll get an error saying it can't convert from int to sbyte, so the value you've put in as 101 is being interpreted as sbyte in the context you're in. 

    If you create an int value, and assign 101 to it, and then try to pass that into the method, it won't work.  So, the following won't compile:

        int value = 101;  
        d.MyMethod(value);    

    Although the compiler can infer with your example that 101 is to be an sbyte, it can't infer in this context, because 101 isn't in the immediate context.  It may be immediate to you or I, but it isn't immediate enough for the compiler.


    David Morton - http://blog.davemorton.net/
    Thursday, November 13, 2008 7:34 PM
    Moderator
  •  

    But if that is the case, it appears that the compiler is violating a rule to downcast
    using an explicit conversion, because it looks like there is some kind of conversion going
    on.

    Or is the 101 literal, in this "inference context," initially being "viewed" as an
    sbyte and not an integer?

    I realize I am probably splitting hairs, but I want to make sure I get these fundamentals straight.

    Thursday, November 13, 2008 9:05 PM
  • The compiler is inferring the type of 101 as being sbyte, not int.  Technically, it's never a conversion.

    If the value you place there cannot be inferred to be an sbyte (either it's a variable of some other type, or it's out of range for the type specified by the parameter declaration in the method head), then you'll get a compile error.
    David Morton - http://blog.davemorton.net/
    • Marked as answer by landgazr Thursday, November 13, 2008 10:51 PM
    Thursday, November 13, 2008 9:11 PM
    Moderator
  • David M Morton said:

    The compiler is inferring the type of 101 as being sbyte, not int.  Technically, it's never a conversion.

    If the value you place there cannot be inferred to be an sbyte (either it's a variable of some other type, or it's out of range for the type specified by the parameter declaration in the method head), then you'll get a compile error.


    David Morton - http://blog.davemorton.net/



    (emphasis mine)

    Nice bit of syntactical C# subterfuge there. Ha ha!

    Sometimes I like the compiler fixing these kinds of things transparently and sometimes I don't. Depends on what your needs are.

    Much obliged, David.

    Thursday, November 13, 2008 10:51 PM