Every function member invocation includes an argument list, which provides
actual values or variable
references for the parameters of the function member. The syntax for
specifying the argument list of a
function member invocation depends on the function member category:
?For instance constructors, methods, and delegates, the arguments are
specified as an argument-list, as
described below.
?For properties, the argument list is empty when invoking the get
accessor, and consists of the
expression specified as the right operand of the assignment operator when
invoking the set accessor.
?For events, the argument list consists of the expression specified as the
right operand of the += or -=
operator.
?For indexers, the argument list consists of the expressions specified
between the square brackets in the
indexer access. When invoking the set accessor, the argument list
additionally includes the expression
specified as the right operand of the assignment operator.
?For user-defined operators, the argument list consists of the single
operand of the unary operator or the
two operands of the binary operator.
The arguments of properties (?7.6), events (?7.7), and user-defined
operators (?7.9) are always passed as
value parameters (?7.5.1.1). The arguments of indexers (?7.8) are always
passed as value parameters
(?7.5.1.1) or parameter arrays (?7.5.1.4). Reference and output
parameters are not supported for these
categories of function members.
The arguments of an instance constructor, method, or delegate invocation
are specified as an argument-list:
argument-list:
argument
argument-list , argument
argument:
expression
ref variable-reference
out variable-reference
An argument-list consists of one or more arguments, separated by commas.
Each argument can take one of
the following forms:
?An expression, indicating that the argument is passed as a value
parameter (?7.5.1.1).
?The keyword ref followed by a variable-reference (?2.3.3), indicating
that the argument is passed as a
reference parameter (?7.5.1.2). A variable must be definitely assigned (?2.
3) before it can be passed
as a reference parameter. A volatile field (?7.4.3) cannot be passed as a
reference parameter.
?The keyword out followed by a variable-reference (?2.3.3), indicating
that the argument is passed as
an output parameter (?7.5.1.3). A variable is considered definitely
assigned (?2.3) following a
function member invocation in which the variable is passed as an output
parameter. A volatile field
(?7.4.3) cannot be passed as an output parameter.
During the run-time processing of a function member invocation (?4.4.3),
the expressions or variable
references of an argument list are evaluated in order, from left to right,
as follows:
Chapter 14 Expressions
133
?For a value parameter, the argument expression is evaluated and an
implicit conversion (?3.1) to the
corresponding parameter type is performed. The resulting value becomes the
initial value of the value
parameter in the function member invocation.
?For a reference or output parameter, the variable reference is evaluated
and the resulting storage location
becomes the storage location represented by the parameter in the function
member invocation. If the
variable reference given as a reference or output parameter is an array
element of a reference-type, a
run-time check is performed to ensure that the element type of the array is
identical to the type of the
parameter. If this check fails, a System.ArrayTypeMismatchException is
thrown.
Methods, indexers, and instance constructors may declare their right-most
parameter to be a parameter array
(?7.5.1.4). Such function members are invoked either in their normal form
or in their expanded form
depending on which is applicable (?4.4.2.1):
?When a function member with a parameter array is invoked in its normal
form, the argument given for
the parameter array must be a single expression of a type that is
implicitly convertible (?3.1) to the
parameter array type. In this case, the parameter array acts precisely like
a value parameter.
?When a function member with a parameter array is invoked in its expanded
form, the invocation must
specify zero or more arguments for the parameter array, where each argument
is an expression of a type
that is implicitly convertible (?3.1) to the element type of the parameter
array. In this case, the
invocation creates an instance of the parameter array type with a length
corresponding to the number of
arguments, initializes the elements of the array instance with the given
argument values, and uses the
newly created array instance as the actual argument.
The expressions of an argument list are always evaluated in the order they
are written. [Example: Thus, the
example
class Test
{
static void F(int x, int y, int z) {
System.Console.WriteLine("x = {0}, y = {1}, z = {2}", x, y, z);
}
static void Main() {
int i = 0;
F(i++, i++, i++);
}
}
produces the output
x = 0, y = 1, z = 2
end example]
The array covariance rules (?9.5) permit a value of an array type A[] to
be a reference to an instance of an
array type B[], provided an implicit reference conversion exists from B to
A. Because of these rules, when
an array element of a reference-type is passed as a reference or output
parameter, a run-time check is
required to ensure that the actual element type of the array is identical
to that of the parameter. [Example: In
the example
class Test
{
static void F(ref object x) {?}
static void Main() {
object[] a = new object[10];
object[] b = new string[10];
F(ref a[0]); // Ok
F(ref b[1]); // ArrayTypeMismatchException
}
}
the second invocation of F causes a System.ArrayTypeMismatchException to be
thrown because the
actual element type of b is string and not object. end example]
C# LANGUAGE SPECIFICATION
134
When a function member with a parameter array is invoked in its expanded
form, the invocation is
processed exactly as if an array creation expression with an array
initializer (?4.5.10.2) was inserted around
the expanded parameters. [Example: For example, given the declaration
void F(int x, int y, params object[] args);
the following invocations of the expanded form of the method
F(10, 20);
F(10, 20, 30, 40);
F(10, 20, 1, "hello", 3.0);
correspond exactly to
F(10, 20, new object[] {});
F(10, 20, new object[] {30, 40});
F(10, 20, new object[] {1, "hello", 3.0});
In particular, note that an empty array is created when there are zero
arguments given for the parameter
array. end example]