Модификатор параметров in (справочник по C#)in parameter modifier (C# Reference)

Ключевое in инициирует передачу аргументов по ссылке.The in keyword causes arguments to be passed by reference. В результате этот формальный параметр становится псевдонимом для аргумента, который должен представлять собой переменную.It makes the formal parameter an alias for the argument, which must be a variable. Другими словами, любая операция в параметре осуществляется с аргументом.In other words, any operation on the parameter is made on the argument. Оно аналогично ключевым словам ref и out, за исключением того, что аргументы in не могут быть изменены вызываемым методом.It is like the ref or out keywords, except that in arguments cannot be modified by the called method. В то время как аргументы ref могут быть изменены, аргументы out должны быть изменены вызывающим объектом, и эти изменения отслеживаются в вызывающем контексте.Whereas ref arguments may be modified, out arguments must be modified by the called method, and those modifications are observable in the calling context.

int readonlyArgument = 44;
InArgExample(readonlyArgument);
Console.WriteLine(readonlyArgument);     // value is still 44

void InArgExample(in int number)
{
    // Uncomment the following line to see error CS8331
    //number = 19;
}

Предыдущий пример показывает, что модификатор in обычно не требуется в месте вызова.The preceding example demonstrates that the in modifier is usually unnecessary at the call site. Он нужен только в объявлении метода.It is only required in the method declaration.

Примечание

Ключевое слово in также можно использовать с параметром универсального типа для указания на то, что тип параметра является контравариантным, в рамках оператора foreach или предложения join в запросе LINQ.The in keyword can also be used with a generic type parameter to specify that the type parameter is contravariant, as part of a foreach statement, or as part of a join clause in a LINQ query. Дополнительные сведения об использовании ключевого слова in в таких контекстах см. в разделе in, где приведены все соответствующие ссылки.For more information on the use of the in keyword in these contexts, see in, which provides links to all those uses.

Переменные, передаваемые в качестве аргументов in, требуется инициализировать перед передачей в вызов метода.Variables passed as in arguments must be initialized before being passed in a method call. Но вызванный метод не может присвоить значение или изменить аргумент.However, the called method may not assign a value or modify the argument.

Модификатор параметра in доступен в C# 7.2 и более поздних версиях.The in parameter modifier is available in C# 7.2 and later. Предыдущие версии создают ошибку компилятора CS8107 ("Функция "Ссылки только для чтения" недоступна в C# 7.0.Previous versions generate compiler error CS8107 ("Feature 'readonly references' is not available in C# 7.0. Используйте языковую версию 7.2 или выше"), чтобы настроить языковую версию компилятора, см. Выбор версии языка C#.Please use language version 7.2 or greater.") To configure the compiler language version, see Select the C# language version.

Ключевые слова in, ref и out не считаются частью сигнатуры метода для разрешения перегрузки.The in, ref, and out keywords are not considered part of the method signature for the purpose of overload resolution. Таким образом, методы не могут быть перегружены, если единственное различие состоит в том, что один метод принимает аргумент ref или in, а другой — out.Therefore, methods cannot be overloaded if the only difference is that one method takes a ref or in argument and the other takes an out argument. Следующий код, например, компилироваться не будет.The following code, for example, will not compile:

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on in, ref and out".
    public void SampleMethod(in int i) { }
    public void SampleMethod(ref int i) { }
}

Перегрузка, основанная на наличии in, допустима:Overloading based on the presence of in is allowed:

class InOverloads
{
    public void SampleMethod(in int i) { }
    public void SampleMethod(int i) { }
}

Правила разрешения перегрузкиOverload resolution rules

Разобраться в правилах разрешения перегрузки для методов по значению и аргументам in можно, поняв основания для применения аргументов in.You can understand the overload resolution rules for methods with by value vs. in arguments by understanding the motivation for in arguments. Определение методов с помощью параметров in является потенциальной оптимизацией производительности.Defining methods using in parameters is a potential performance optimization. Некоторые аргументы типа struct могут иметь большой размер, и при вызове методов в ограниченных циклах или критических путях кода стоимость копирования этих структур имеет определяющее значение.Some struct type arguments may be large in size, and when methods are called in tight loops or critical code paths, the cost of copying those structures is critical. Методы объявляют параметры in, чтобы указать, что аргументы можно безопасно передавать по ссылке, так как вызываемый метод не изменяет состояние этого аргумента.Methods declare in parameters to specify that arguments may be passed by reference safely because the called method does not modify the state of that argument. Передача этих аргументов по ссылке позволяет избежать (потенциально) дорогого копирования.Passing those arguments by reference avoids the (potentially) expensive copy.

Указывать in для аргументов в месте вызова обычно необязательно.Specifying in for arguments at the call site is typically optional. Нет семантического различия между передачей аргументов по значению и передачей их по ссылке с помощью модификатора in.There is no semantic difference between passing arguments by value and passing them by reference using the in modifier. Модификатор in в месте вызова является необязательным, так как не нужно указывать, что значение аргумента может изменяться.The in modifier at the call site is optional because you don't need to indicate that the argument's value might be changed. Вы явным образом добавляете модификатор in в место вызова, чтобы аргумент передавался по ссылке, а не по значению.You explicitly add the in modifier at the call site to ensure the argument is passed by reference, not by value. Явное использование in приводит к двум результатам.Explicitly using in has the following two effects:

Во-первых, указание in в месте вызова вынуждает компилятор выбрать метод, определенный с помощью соответствующего параметра in.First, specifying in at the call site forces the compiler to select a method defined with a matching in parameter. В противном случае, когда два метода отличаются только наличием in, перегрузка по значению подходит лучше.Otherwise, when two methods differ only in the presence of in, the by value overload is a better match.

Во-вторых, указав in, вы объявляете о намерении передать аргумент по ссылке.Second, specifying in declares your intent to pass an argument by reference. Аргумент, используемый с in, должен представлять расположение, на которое можно сослаться напрямую.The argument used with in must represent a location that can be directly referred to. Такие же общие правила применяются к аргументам out и ref: вы не можете использовать константы, обычные свойства или другие выражения, возвращающие значения.The same general rules for out and ref arguments apply: You cannot use constants, ordinary properties, or other expressions that produce values. В противном случае пропуск in в месте вызова сообщает компилятору, что вы разрешите ему создать временную переменную для передачи с помощью ссылки на метод, доступной только для чтения.Otherwise, 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. Компилятор создает временную переменную, чтобы преодолеть некоторые ограничения для аргументов in:The compiler creates a temporary variable to overcome several restrictions with in arguments:

  • Временная переменная позволяет использовать константы времени компиляции, например параметры in.A temporary variable allows compile-time constants as in parameters.
  • Временная переменная позволяет использовать свойства или другие выражения для параметров in.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.

Во всех предыдущих случаях компилятор создает временную переменную, хранящую значение константы, свойства или другого выражения.In all the preceding instances, the compiler creates a temporary variable that stores the value of the constant, property, or other expression.

Эти правила проиллюстрированы в следующем коде:The following code illustrates these rules:

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // OK, temporary variable created.
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // OK, temporary int created with the value 0
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // passed by readonly reference
Method(in i); // passed by readonly reference, explicitly using `in`

Теперь предположим, что был доступен другой метод, использующий аргументы по значению.Now, suppose another method using by value arguments was available. Результаты изменяются, как показано в следующем коде:The results change as shown in the following code:

static void Method(int argument)
{
    // implementation removed
}

static void Method(in int argument)
{
    // implementation removed
}

Method(5); // Calls overload passed by value
Method(5L); // CS1503: no implicit conversion from long to int
short s = 0;
Method(s); // Calls overload passed by value.
Method(in s); // CS1503: cannot convert from in short to in int
int i = 42;
Method(i); // Calls overload passed by value
Method(in i); // passed by readonly reference, explicitly using `in`

Аргумент передается по ссылке только в последнем вызове метода.The only method call where the argument is passed by reference is the final one.

Примечание

Для простоты предыдущий код использует int в качестве типа аргумента.The preceding code uses int as the argument type for simplicity. Так как по размеру int не больше ссылки на большинстве современных компьютеров, не имеет смысла передавать один int в качестве ссылки, доступной только для чтения.Because int is no larger than a reference in most modern machines, there is no benefit to passing a single int as a readonly reference.

Ограничения для параметров inLimitations on in parameters

Ключевые слова in, ref и out запрещено использовать для следующих типов методов.You can't use the in, ref, and out keywords for the following kinds of methods:

  • Асинхронные методы, которые определяются с помощью модификатора async.Async methods, which you define by using the async modifier.
  • Методы итератора, которые включают оператор yield return или yield break.Iterator methods, which include a yield return or yield break statement.

Спецификация языка C#C# Language Specification

Дополнительные сведения см. в спецификации языка C#.For more information, see the C# Language Specification. Спецификация языка является предписывающим источником информации о синтаксисе и использовании языка C#.The language specification is the definitive source for C# syntax and usage.

См. такжеSee also