2

It is not clear why C# doesn't allow calling a method passing a literal together with the in parameter modifier; at the same time, when the literal passed to the method without the in parameter modifier the code compiles.

Here is a code example that demonstrates this behavior (C# 7.3):

class Program
{
    static void Main(string[] args)
    {
        string s = string.Empty;

        //These two lines compile 
        WriteStringToConsole(in s);
        WriteStringToConsole("my string");

        //Error CS8156  An expression cannot be used in this context because it may not be passed or returned by reference 
        WriteStringToConsole(in "my string");
    }

    public static void WriteStringToConsole (in string s)
    {
        Console.WriteLine(s);
    }
}
Corentin Pane
  • 4,794
  • 1
  • 12
  • 29
V. S.
  • 1,086
  • 14
  • 14

3 Answers3

5

As specified in the C# language reference, you cannot use a constant with the in keyword as an argument:

The argument used with in must represent a location that can be directly referred to. The same general rules for out and ref arguments apply: you cannot use constants, ordinary properties, or other expressions that produce values.

Corentin Pane
  • 4,794
  • 1
  • 12
  • 29
1

In C# 7.2, “in parameter” has been introduced which allows passing read-only reference of a variable. Before C# 7.2, we used “ref” and “out” keywords for passing the references of a variable. “Out” is meant for output only whereas ‘ref’ is meant for input and output both. However, if we had to pass a read-only reference, i.e., passing a variable as input only, then there was no direct option for that. So, in C# 7.2, “in parameter” has been introduced for this purpose

You can refer below answer for the right use in parameter

https://stackoverflow.com/a/52825832/3992001

       static void Main(string[] args)
        {
            WriteStringToConsole("test"); // OK, temporary variable created.
            string test = "test";
            WriteStringToConsole(test); // OK, temporary int created with the value 0
            WriteStringToConsole(in test); // passed by readonly reference, explicitly using `in`
            //Not allowed
            WriteStringToConsole(in "test"); //Error CS8156  An expression cannot be used in this context because it may not be passed or returned by reference

        }
        static void WriteStringToConsole(in string argument)
        {
            Console.WriteLine(argument);
        }
Jayakumar Thangavel
  • 1,884
  • 1
  • 22
  • 29
0

It is clear why the in modifier can't be used with a literal while calling a method with the in parameter modifier; the ref and out modifiers don't allow it too:

in parameter modifier (C# Reference)

The argument used with in must represent a location that can be directly referred to. The same general rules for out and ref arguments apply: You cannot use constants, ordinary properties, or other expressions that produce values.

When you want to pass to a method with the in parameter modifier a literal without the in modifier then the compiler creates a temporary variable and uses a reference to this variable calling the method. It is done for the following reasons:

in parameter modifier (C# Reference)

Omitting in at the call site informs the compiler that you will allow it to create a temporary variable to pass by read-only reference to the method. The compiler creates a temporary variable to overcome several restrictions with in arguments:

  • A temporary variable allows compile-time constants as in parameters.
  • A temporary variable allows properties, or other expressions for in parameters.
  • A temporary variable allows arguments where there is an implicit conversion from the argument type to the parameter type.

To summarize, both options are allowed since each of them has a different usage case, but eventually, a read-only reference to a variable used anyway.

V. S.
  • 1,086
  • 14
  • 14