C# Method Parameters and Arguments: Pass Values with Confidence
A method call supplies values to a contract. Learn where each input goes, what a helper can change, and how named arguments and sensible defaults make calls easier to understand.
What you will understand
- Distinguish declared parameters from supplied arguments.
- Match arguments by position, name and compatible type.
- Trace an integer copy and explicitly assign a returned result.
- Explain array element mutation versus parameter reassignment.
- Use named arguments for inputs with similar types.
- Omit optional arguments deliberately and distinguish defaults from zero.
- Recognize explicit ref and its initialized-variable requirement.
- Repair a call that compiles but gives the wrong meaning to its inputs.
Parameters describe inputs; arguments supply them
You already know how to declare a method and use its result. Now look closely at the boundary between a call and its helper. A parameter is a typed variable declared in the method’s parentheses. An argument is a value or expression supplied in the call. The declaration is the input contract; each call supplies a particular set of inputs.
In CalculateSubtotal(decimal unitPrice, int quantity), unitPrice and quantity are parameters. In CalculateSubtotal(price, copies), price and copies are argument expressions. With positional arguments, the first value supplies the first parameter and the second supplies the second. The caller’s variable names do not have to match the parameter names.
Before running the first example, trace price → unitPrice and copies → quantity on paper. Then follow the multiplication and the returned amount. Each editor is a separate complete Program.cs with one Main entry point and static helper methods, matching the previous lesson’s structure.
Program.cs · Match supplied arguments to declared parameters
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Subtotal: 37.50
price supplies unitPrice and copies supplies quantity. The caller and helper do not need matching variable names: positional arguments match by location. The method receives 12.50m and 3 for this call, then returns 37.50m.
Program.cs · An argument can be an expression
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Subtotal: 18.00
The argument expressions are evaluated before the helper body runs. unitPrice receives 6m and quantity receives 3; the method does not receive the source expressions as instructions to reevaluate later.
Count, position and compatible types all matter
A required parameter must receive an argument. C# checks that arguments can convert to their parameter types; it does not parse text just because that text looks like a number. A string from Console.ReadLine needs an explicit parsing step before it can be supplied to an int parameter.
The compiler can catch missing arguments and incompatible types. It cannot catch every incorrect ordering: when two parameters share a type, swapping their arguments may compile and calculate the wrong result. Think about meaning and units as well as the type written in the declaration.
Two examples below intentionally fail compilation. Read the diagnostic as evidence about the contract rather than assuming the runner failed. Repair the missing quantity in one example and supply an integer in the other. Do not fix an absent input by inventing a default unless the method’s actual requirements allow one.
Program.cs · A string is not an integer argument
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: the second argument cannot convert from string to int.Even though the string contains a digit, its type is string. Parse external text before this call, following the user-input lesson. Named arguments do not remove type checks.
Program.cs · Required parameters need arguments
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: no argument was supplied for quantity.quantity has no default value, so every valid call must supply it. C# does not invent a value from a similarly named caller variable. An optional parameter is an explicit design decision, not an automatic missing-input repair.
A normal integer parameter receives a value copy
By default, arguments are passed by value. For an int, the helper gets its own copy of the integer. Giving the parameter the same name as the caller’s variable does not connect their storage. Changing the parameter changes the helper’s local variable.
Imagine Main’s score box containing 10 and a separate parameter box also containing 10. Incrementing the second box produces 11 there while the first remains 10. When the helper returns, its local parameter is no longer the caller’s place to store a result.
If the caller needs a new score, return the computed integer and assign it in Main. This makes the change visible at the call site. Without that assignment, merely calling a method that returns a new value still leaves the original variable unchanged.
Program.cs · Changing an integer parameter changes its local copy
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Inside: 11
Caller: 10
Main and AddPoint have separate integer variables, even though both are named score. The call copies the value 10. Incrementing the parameter changes that copy, so the caller still holds 10 after the method returns.
Program.cs · Return the new value and assign it deliberately
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Caller: 11
The argument is still passed by value. Main changes because its assignment stores the returned result, not because the parameter secretly refers to Main’s variable. For a single calculated result, this explicit pattern is usually easy to follow.
An array reference is copied; the array is shared
An array is a reference type. Passing it by value copies the reference to its array object, not all the elements into a new independent array. The caller variable and parameter are separate variables that initially point to the same object.
Changing values[0] writes to the shared object, so reading scores[0] afterward shows the change. In contrast, assigning values = new int[] { 99, 100 } changes which object the parameter refers to. It does not reassign the caller’s scores variable. Both examples use ordinary by-value parameters.
This distinction matters when you design a helper: does it inspect data, mutate the supplied data, or return replacement data? Make side effects clear in its name and explanation. The first-element helper below assumes a non-null, nonempty array; calling it with an empty array would access an invalid index. It is not a general array-validation routine.
Program.cs · Two reference copies can reach the same array
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Caller first: 11
The parameter receives a copy of the array reference, not a separate copy of every element. Both references reach the same array object. Updating element zero is visible through the caller’s reference. This helper assumes a non-null array containing at least one element.
Program.cs · Replacing the parameter does not replace the caller’s reference
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Inside first: 99
Caller first: 10
Assigning a new reference changes only the parameter variable. scores in Main still refers to the original array. Contrast values[0] = 99, which changes an element of the existing object, with values = new int[] { 99, 100 }, which redirects the local parameter.
Named arguments make similar inputs easier to read
A named argument uses parameterName: expression at the call site. The name must match a parameter in the declaration, including case. It does not declare a new variable in the caller, and it does not bypass type checking.
Using names is particularly helpful for adjacent amounts or flags whose positions are easy to confuse. In CalculateTotal, subtotal, delivery and discount all use decimal but have different roles in the formula. A labeled call lets the reader check each amount against the requirement.
All-named arguments can be written in a different order from the declaration. When mixing styles, a simple readable convention is to put positional arguments first and named arguments afterward. C# also permits certain in-position named arguments before positional ones; avoid relying on those subtler forms while learning. Argument expressions evaluate in their written call-site order, so do not hide interdependent changes inside them.
Program.cs · Name each amount when positions would be unclear
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Total: 29.00
Each label matches a parameter declared by CalculateTotal. All arguments here are named, so their written order can differ from declaration order. The formula adds delivery and subtracts discount; naming makes those different roles visible even though all three types are decimal.
Defaults are used when an optional argument is omitted
An optional parameter declares a default, such as decimal delivery = 4m. A call that omits that argument uses the declared default. A call that explicitly supplies zero uses zero instead: omitted and zero are different choices. Choose a default only when that meaning is sensible for every caller that leaves it out.
In these declarations, required parameters come before optional parameters. To supply a later optional argument while omitting an earlier one, use its name. CalculateTotal(30m, discount: 5m) keeps delivery at four; a blank slot between commas is not valid syntax.
Optional defaults in these examples are constants. They are not a way to ask the compiler to run an arbitrary calculation in the declaration. Defaults are part of a public contract, and changing them can affect callers; a clearer method or a required argument can be better than a surprising implicit choice. The third compiler failure below shows an invalid parameter order.
Program.cs · Omit a default or supply a value explicitly
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Default: 34.00
Free delivery: 30.00
Discount only: 29.00
Omitting delivery uses 4m; explicitly supplying zero uses zero. In the third call, naming discount skips delivery while keeping its default. You cannot leave an empty comma-separated argument slot. subtotal remains required in every call.
Program.cs · Required parameters come before optional parameters
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Compilation fails: optional parameters must appear after required parameters.The declaration itself is invalid. Put required subtotal before optional delivery, then adjust calls to match the corrected contract. Changing a call alone cannot repair this definition.
Use explicit reference passing only when you mean it
Ordinary by-value passing is the baseline, including for arrays. The ref modifier changes the contract: a ref parameter can refer to the caller’s variable itself. In the small integer example, ref is written in both the declaration and call, and the caller initializes score before passing it.
Keep two ideas separate: a reference-type object passed by value, and an argument explicitly passed by reference. The shared-array example needed no ref because both references reached the same mutable object. ref becomes relevant when the operation intentionally modifies the caller’s variable, including potentially replacing a caller’s object reference.
You previously used out with TryParse: that modifier lets a method assign an output variable and requires assignment before normal return. It is a different contract from ref, which starts with an initialized caller variable. For this lesson’s single numeric calculation, return plus assignment remains the clearest choice. Compare the results, then practice both value flow and argument meaning in the repair and lab.
Program.cs · An explicit ref parameter can update a caller variable
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Caller: 11
ref appears at both the declaration and call. It makes the parameter refer to the caller’s variable rather than receiving an ordinary value copy. The variable must already be initialized. Prefer a returned result for a simple calculation unless modifying the supplied variable is an intentional part of the contract.
Guided repair: correct the argument meanings
The requirement is subtotal 30m plus delivery 4m minus discount 5m, so the result must be 29.00. The existing call produces 31.00 even though it compiles. Fix the call without changing the correct formula or the parameter declaration.
Program.cs · A valid call can still swap meanings
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Total: 31.00
The requirement is subtotal 30, delivery 4 and discount 5, giving 29. The compiler accepts this call because all three arguments are decimal. But the second position means delivery, so this call adds 5 and subtracts 4. Compatible types cannot prove that the amounts have the intended meanings.
Repair checkpoints
- Map the second positional argument to delivery, not discount.
- Map the third positional argument to discount.
- Use all three parameter names so the intended roles can be checked at the call site.
- Keep CalculateTotal free of console output.
- Verify 30 + 4 - 5 = 29 before comparing the output.
Reveal the repair and explanation
Program.cs · Use named arguments to show the intended amounts
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Total: 29.00
The unchanged formula now receives the intended values. Named arguments clarify an interface; they do not validate business rules or prevent a developer from attaching the wrong value to a label. Check the requirement as well as the syntax.
Independent lab: connect inputs, defaults and returned results
Repair a small practice-planning report. Store the increased practice duration in the caller, then calculate a fee using explicitly named amounts. Preserve a useful default without making required inputs optional.
Acceptance checklist
- Change AddPractice to return int, accepting required minutes and optional extra = 10.
- Store its returned value back into minutes in Main.
- Keep CalculateTotal with required subtotal and optional delivery = 4m and discount = 0m.
- Use named subtotal, delivery and discount arguments for the fee report.
- Print Caller minutes: 30 and Total: 29.00 for the reference inputs.
- Keep arithmetic in the helpers and formatting in Main.
- Assume nonnegative values, discount no greater than subtotal and arithmetic within range.
Program.cs · Practice planning starter
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Caller minutes: 20
Total: 31.00
Two mistakes are visible: the practice helper changes only its integer copy, and the amounts are swapped in the positional fee call. Use the lab contract to return a new practice duration and name the fee arguments. This starter intentionally runs with incorrect results.
Show hints
- Replacing a local integer parameter does not replace Main’s integer. Return minutes + extra.
- Use minutes = AddPractice(minutes); to preserve the returned value.
- The fee formula is already correct; fix the argument meanings instead.
Reveal the reference solution
Program.cs · Practice planning reference solution
Predict the result, edit Program.cs, then run your program.
Standard input · optional
Select Run code to compile and execute this program.
Caller minutes: 30
Total: 29.00
AddPractice returns the computed duration and Main explicitly stores it. extra defaults to ten when omitted. Named fee inputs preserve their intended roles. The exercise assumes nonnegative inputs, discount no greater than subtotal, and arithmetic within range; it does not define a real billing or scheduling system.
Changed-input checks
- Change initial minutes to 0: the default increase produces 10.
- Supply extra: 0 explicitly: initial 20 stays 20.
- Supply extra: 5: initial 20 becomes 25.
- CalculateTotal(30m) returns 34.00 using both defaults.
- CalculateTotal(30m, delivery: 0m, discount: 0m) returns 30.00.
- CalculateTotal(30m, discount: 30m) returns 4.00 with default delivery.
Recap: what crosses the method boundary
Check which parameter receives each argument, what is copied, and whether the helper changes an object or returns a new value.
parameter- A typed input variable in the declaration.
argument- A supplied value or expression at the call.
by value: int- The helper receives an independent integer copy.
by value: array- A copied reference still reaches the same array object.
name: value- Match the argument to the declared parameter name.
parameter = default- Use the default only when the argument is omitted.
ref variable- Explicitly permit access to the initialized caller variable.
return and assignment- Calculate a new value and let the caller store it explicitly.
Frequently asked questions
Are parameter names and caller variable names required to match?
No. Positional arguments match by position. Named argument labels, however, must match the declared parameter names.
Does passing an array copy its elements?
Not with an ordinary parameter. The reference is copied, so both references can reach the same array. Create a separate array explicitly when you need independent elements.
Why did changing the parameter not change my integer?
The helper received a value copy. Return the new result and assign it in the caller, or deliberately design a ref contract when that behavior is necessary.
Is an array automatically passed by reference?
Its reference is passed by value by default. Element mutation can be visible, but assigning a new array to the parameter does not replace the caller’s variable.
Does named mean optional?
No. Naming controls how an argument matches a parameter; a declared default makes the argument optional. A required parameter can be supplied by name.
Can I skip an optional argument with an empty comma?
No. Name a later argument to keep an earlier optional parameter at its default. Explicit zero is a supplied value, not an omission.
Can you trace the supplied values?
Distinguish value copies, shared arrays, named inputs and omitted defaults. Read the explanation after checking your answers.
Next step and references
Parameters define typed inputs and calls supply arguments. Ordinary passing copies values, including array references. Named inputs clarify meaning, defaults apply only when omitted, and explicit ref changes the contract.
Next is C# Method Overloading. You will use one operation name with different parameter lists and learn how the compiler chooses a matching call.
Official references
Original SovranCode explanations, examples and exercises. Technical details were checked against these references.
Last updated: .