We now consider how to write a method with multiple parameters. Figure 7.3 defines Maximum
method that determines and returns the largest of three double
values. When the app begins execution, the Main
method (lines 8–23) executes. Line 19 calls method Maximum
(declared in lines 26–43) to determine and return the largest of its three double
arguments. In Section 7.4.3, we’ll discuss the use of the + operator in line 22. The sample outputs show that Maximum
determines the largest value regardless of whether that value is the first, second or third argument.
static
Method Maximum
’s declaration begins with keyword static
, which enables the Main
method (another static
method) to call Maximum
as shown in line 19 without creating an object of class MaximumFinder
and without qualifying the method name with the class name MaximumFinder
—static
methods in the same class can call each other directly.
Maximum
Consider the declaration of method Maximum
(lines 26–43). Line 26 indicates that the method returns a double
value, that the method’s name is Maximum
and that the method requires three double
parameters (x
, y
and z
) to accomplish its task. When a method has more than one parameter, the parameters are specified as a comma-separated list. When Maximum
is called in line 19, the parameter x
is initialized with the value of the argument number1
, the parameter y
is initialized with the value of the argument number2
and the parameter z
is initialized with the value of the argument number3
. There must be one argument in the method call for each required parameter in the method declaration. Also, each argument must be consistent with the type of the corresponding parameter. For example, a parameter of type double
can receive values like 7.35
(a double
), 22
(an int
) or –0.03456
(a double
), but not string
s like "hello"
. Section 7.6 discusses the argument types that can be provided in a method call for each parameter of a simple type. Note the use of type double
’s Parse
method in lines 12, 14 and 16 to convert into double
values the string
s typed by the user.
Declaring method parameters of the same type as double x, y
instead of double x, double y
is a syntax error—a type is required for each parameter in the parameter list.
To determine the maximum value, we begin with the assumption that parameter x
contains the largest value, so line 28 declares local variable maximumValue
and initializes it with the value of parameter x
. Of course, it’s possible that parameter y
or z
contains the largest value, so we must compare each of these values with maximumValue
. The if
statement at lines 31–34 determines whether y
is greater than maximumValue
. If so, line 33 assigns y
to maximumValue
. The if
statement at lines 37–40 determines whether z
is greater than maximumValue
. If so, line 39 assigns z
to maximumValue
. At this point, the largest of the three values resides in maximumValue
, so line 42 returns that value to line 19 where it’s assigned to the variable result
. When program control returns to the point in the app where Maximum
was called, Maximum
’s parameters x
, y
and z
are no longer accessible. Methods can return at most one value; the returned value can be a value type that contains one or more values (implemented as a struct
; Section 10.13) or a reference to an object that contains one or more values.
string
s with ConcatenationC# allows string
objects to be created by assembling smaller string
s into larger string
s using operator +
(or the compound assignment operator +=
). This is known as string concatenation
. When both operands of operator +
are string
objects, the +
operator creates a new string
object containing copies of the characters in its left operand followed by copies of the characters in its right operand. For example, the expression "hello " + "there"
creates the string "hello there"
without disturbing the original string
s.
In line 22, the expression "Maximum is: " + result
uses operator +
with operands of types string
and double
. Every simple-type value has a string
representation. When one of the +
operator’s operands is a string
, the other is implicitly converted to a string
, then the two string
s are concatenated. So, in line 22, the double
value is converted to its string
representation and placed at the end of "Maximum is: "
. If there are any trailing zeros in a double
value, these are discarded. Thus, the string
representation of 9.3500 is "9.35"
.
string
If a bool
is concatenated with a string
, the bool
is converted to the string "True"
or "False"
(each is capitalized). In addition, every object has a ToString
method that returns a string
representation of that object. When an object is concatenated with a string
, the object’s ToString
method is called implicitly to obtain the string
representation of the object. If the object is null
, an empty string is written.
If a type does not define a ToString
method, the default ToString
implementation returns a string
containing the type’s fully qualified name—that is, the namespace in which the type is defined followed by a dot (.
) and the type name (e.g., System.Object
for the .NET class Object
). Each type you create can declare a custom ToString
method, as you’ll do in Chapter 8 for a Card
class that represents a playing card in a deck of cards.
string
s with string
InterpolationLine 22 of Fig. 7.3, of course, could also be written using string
interpolation as
Console.WriteLine($"Maximum is: {result}");
As with string
concatenation, using string
interpolation to insert an object into a string
implicitly calls the object’s ToString
method to obtain the object’s string
representation.
string
LiteralsWhen a large string
literal or interpolated string
is typed into an app’s source code, you can break that string
into several smaller string
s and place them on multiple lines for readability. The string
s can be reassembled using string
concatenation. We discuss the details of string
s in Chapter 16.
It’s a syntax error to break a string
literal or interpolated string
across multiple lines of code. If a string
does not fit on one line, you can split it into several smaller string
s and use concatenation to form the desired string
.
Confusing the string concatenation +
operator with the addition +
operator can lead to strange results. The +
operator is left-associative. For example, if y
has the int
value 5
, the expression "y + 2="+ y+2
results in the string "y + 2 = 52"
, not "y + 2 = 7"
, because first the value of y
(5
) is concatenated with the string "y + 2 = "
, then the value 2
is concatenated with the new larger string "y + 2 = 5"
. The expression "y + 2=" + (y + 2)
produces the desired result "y + 2 = 7"
. Using C# 6 string
interpolation eliminates this problem.
Variable result
is a local variable in method Main
because it’s declared in the block that represents the method’s body. Variables should be declared as fields of a class (i.e., as either instance variables or static
variables) only if they’re required for use in more than one method of the class or if the app should save their values between calls to a given method.
Maximum
by Reusing Method Math.Max
Recall from Fig. 7.2 that class Math
’s Max
method can determine the larger of two values. The entire body of our maximum method could also be implemented with nested calls to Math.Max
, as follows:
return Math.Max(x, Math.Max(y, z));
The leftmost Math.Max
call has the arguments x
and Math.Max(y, z
). Before any method can be called, the runtime evaluates all the arguments to determine their values. If an argument is a method call, the call must be performed to determine its return value. So, in the preceding statement, Math.Max(y, z
) is evaluated first to determine the larger of y
and z
. Then the result is passed as the second argument to the first call to Math.Max
, which returns the larger of its two arguments. Using Math.Max
in this manner is a good example of software reuse—we find the largest of three values by reusing Math.Max
, which finds the larger of two values. Note how concise this code is compared to lines 28–42 of Fig. 7.3.