메서드(C#)Methods in (C#)

메서드는 일련의 문을 포함하는 코드 블록입니다.A method is a code block that contains a series of statements. 프로그램을 통해 메서드를 호출하고 필요한 메서드 인수를 지정하여 문을 실행합니다.A program causes the statements to be executed by calling the method and specifying any required method arguments. C#에서는 실행된 모든 명령이 메서드의 컨텍스트에서 수행됩니다.In C#, every executed instruction is performed in the context of a method. Main 메서드는 모든 C# 애플리케이션의 진입점이고 프로그램이 시작될 때 CLR(공용 언어 런타임)에서 호출됩니다.The Main method is the entry point for every C# application and it is called by the common language runtime (CLR) when the program is started.

참고

이 항목에서는 명명된 메서드에 대해 설명합니다.This topic discusses named methods. 익명 함수에 대한 자세한 내용은 익명 함수를 참조하세요.For information about anonymous functions, see Anonymous Functions.

메서드 시그니처Method signatures

메서드는 다음을 지정하여 class 또는 struct에서 선언됩니다.Methods are declared in a class or struct by specifying:

  • public 또는 private와 같은 선택적 액세스 수준입니다.An optional access level, such as public or private. 기본값은 private입니다.The default is private.
  • abstract 또는 sealed와 같은 선택적 한정자입니다.Optional modifiers such as abstract or sealed.
  • 반환 값 또는 메서드에 반환 값이 없는 경우 void입니다.The return value, or void if the method has none.
  • 메서드 이름입니다.The method name.
  • 메서드 매개 변수입니다.Any method parameters. 메서드 매개 변수는 괄호로 묶고 쉼표로 구분합니다.Method parameters are enclosed in parentheses and are separated by commas. 빈 괄호는 메서드에 매개 변수가 필요하지 않음을 나타냅니다.Empty parentheses indicate that the method requires no parameters.

이러한 부분이 결합되어 메서드 시그니처를 구성합니다.These parts together form the method signature.

중요

메서드의 반환 값은 메서드 오버로드를 위한 메서드 서명의 파트가 아닙니다.A return type of a method is not part of the signature of the method for the purposes of method overloading. 그러나 대리자와 대리자가 가리키는 메서드 간의 호환성을 결정할 경우에는 메서드 서명의 부분입니다.However, it is part of the signature of the method when determining the compatibility between a delegate and the method that it points to.

다음 예제에서는 다섯 개의 메서드를 포함하는 Motorcycle이라는 클래스를 정의합니다.The following example defines a class named Motorcycle that contains five methods:

using System;

abstract class Motorcycle
{
   // Anyone can call this.
   public void StartEngine() {/* Method statements here */ }

   // Only derived classes can call this.
   protected void AddGas(int gallons) { /* Method statements here */ }

   // Derived classes can override the base class implementation.
   public virtual int Drive(int miles, int speed) { /* Method statements here */ return 1; }

   // Derived classes can override the base class implementation.
   public virtual int Drive(TimeSpan time, int speed) { /* Method statements here */ return 0; }

   // Derived classes must implement this.
   public abstract double GetTopSpeed();
}

Motorcycle 클래스에는 오버로드된 메서드 Drive가 있습니다.Note that the Motorcycle class includes an overloaded method, Drive. 두 메서드는 이름이 같지만 해당 매개 변수 형식으로 구별되어야 합니다.Two methods have the same name, but must be differentiated by their parameter types.

메서드 호출Method invocation

메서드는 인스턴스 또는 정적 일 수 있습니다.Methods can be either instance or static. 인스턴스 메서드를 호출하려면 개체를 인스턴스화하고 해당 개체에서 메서드를 호출해야 합니다. 인스턴스 메서드는 인스턴스 및 해당 데이터에 대해 작동합니다.Invoking an instance method requires that you instantiate an object and call the method on that object; an instance method operates on that instance and its data. 메서드가 속하는 형식의 이름을 참조하여 정적 메서드를 호출합니다. 정적 메서드는 인스턴스 데이터에 대해 작동하지 않습니다.You invoke a static method by referencing the name of the type to which the method belongs; static methods do not operate on instance data. 개체 인스턴스를 통해 정적 메서드를 호출하려고 하면 컴파일러 오류가 생성됩니다.Attempting to call a static method through an object instance generates a compiler error.

메서드 호출은 필드 액세스와 비슷합니다.Calling a method is like accessing a field. 개체 이름(인스턴스 메서드를 호출하는 경우) 또는 형식 이름(static 메서드를 호출하는 경우) 뒤에 마침표, 메서드 이름 및 괄호를 추가합니다.After the object name (if you are calling an instance method) or the type name (if you are calling a static method), add a period, the name of the method, and parentheses. 인수는 괄호 안에 나열되고 쉼표로 구분됩니다.Arguments are listed within the parentheses and are separated by commas.

메서드 정의는 필요한 모든 매개 변수의 이름 및 형식을 지정합니다.The method definition specifies the names and types of any parameters that are required. 호출자는 메서드를 호출할 때 각 매개 변수에 대해 인수라는 구체적인 값을 제공합니다.When a caller invokes the method, it provides concrete values, called arguments, for each parameter. 인수는 매개 변수 형식과 호환되어야 하지만 인수 이름(호출하는 코드에 사용된 경우)은 메서드에 정의된 명명된 매개 변수와 동일할 필요가 없습니다.The arguments must be compatible with the parameter type, but the argument name, if one is used in the calling code, does not have to be the same as the parameter named defined in the method. 다음 예제에서는 Square 메서드에 i 라는 int 형식의 단일 매개 변수가 포함되어 있습니다.In the following example, the Square method includes a single parameter of type int named i. 첫 번째 메서드 호출은 Square 메서드에 num 이라는 int 형식의 변수를 전달합니다. 두 번째 호출은 숫자 상수, 세 번째 호출은 식을 전달합니다.The first method call passes the Square method a variable of type int named num; the second, a numeric constant; and the third, an expression.

public class Example
{
   public static void Main()
   {
      // Call with an int variable.
      int num = 4;
      int productA = Square(num);

      // Call with an integer literal.
      int productB = Square(12);

      // Call with an expression that evaluates to int.
      int productC = Square(productA * 3);
   }

   static int Square(int i)
   {
      // Store input argument in a local variable.
      int input = i;
      return input * input;
   }
}

가장 일반적인 형태의 메서드 호출은 위치 인수를 사용하며, 메서드 매개 변수와 동일한 순서로 인수를 제공합니다.The most common form of method invocation used positional arguments; it supplies arguments in the same order as method parameters. Motorcycle 클래스의 메서드는 다음 예제와 같이 호출될 수 있습니다.The methods of the Motorcycle class can therefore be called as in the following example. 예를 들어 Drive 메서드 호출에는 메서드 구문의 두 매개 변수에 해당하는 두 개의 인수가 포함되어 있습니다.The call to the Drive method, for example, includes two arguments that correspond to the two parameters in the method's syntax. 첫 번째 인수는 miles 매개 변수의 값이 되고, 두 번째 인수는 speed 매개 변수의 값이 됩니다.The first becomes the value of the miles parameter, the second the value of the speed parameter.

class TestMotorcycle : Motorcycle
{
   public override double GetTopSpeed()
   {
      return 108.4;
   }

   static void Main()
   {

      TestMotorcycle moto = new TestMotorcycle();

      moto.StartEngine();
      moto.AddGas(15);
      moto.Drive(5, 20);
      double speed = moto.GetTopSpeed();
      Console.WriteLine("My top speed is {0}", speed);
   }
}

메서드를 호출할 때 위치 인수 대신 ‘명명된 인수’를 사용할 수도 있습니다.You can also use named arguments instead of positional arguments when invoking a method. 명명된 인수를 사용하는 경우 매개 변수 이름 뒤에 콜론(":")과 인수를 지정합니다.When using named arguments, you specify the parameter name followed by a colon (":") and the argument. 모든 필수 인수가 있기만 하면 메서드의 인수 순서는 중요하지 않습니다.Arguments to the method can appear in any order, as long as all required arguments are present. 다음 예제에서는 명명된 인수를 사용하여 TestMotorcycle.Drive 메서드를 호출합니다.The following example uses named arguments to invoke the TestMotorcycle.Drive method. 이 예제에서는 명명된 인수가 메서드의 매개 변수 목록과 반대 순서로 전달됩니다.In this example, the named arguments are passed in the opposite order from the method's parameter list.

using System;

class TestMotorcycle : Motorcycle
{
   public override int Drive(int miles, int speed)
   {
      return (int) Math.Round( ((double)miles) / speed, 0);
   }

   public override double GetTopSpeed()
   {
      return 108.4;
   }

   static void Main()
   {

      TestMotorcycle moto = new TestMotorcycle();
      moto.StartEngine();
      moto.AddGas(15);
      var travelTime = moto.Drive(speed: 60, miles: 170);
      Console.WriteLine("Travel time: approx. {0} hours", travelTime);
   }
}
// The example displays the following output:
//      Travel time: approx. 3 hours

위치 인수와 명명된 인수 둘 다를 사용하여 메서드를 호출할 수 있습니다.You can invoke a method using both positional arguments and named arguments. 그러나 명명된 인수가 올바른 위치에 있는 경우에만 명명된 인수 뒤에 위치 인수를 사용할 수 있습니다.However, positional arguments can only follow named arguments when the named arguments are in the correct positions. 다음 예제에서는 위치 인수 하나와 명명된 인수 하나를 사용하여 이전 예제의 TestMotorcycle.Drive 메서드를 호출합니다.The following example invokes the TestMotorcycle.Drive method from the previous example using one positional argument and one named argument.

var travelTime = moto.Drive(170, speed: 55);

상속 및 재정의된 메서드Inherited and overridden methods

형식은 해당 형식에서 명시적으로 정의된 멤버 외에도 기본 클래스에서 정의된 멤버를 상속합니다.In addition to the members that are explicitly defined in a type, a type inherits members defined in its base classes. 관리되는 형식 시스템의 모든 형식이 직접 또는 간접적으로 Object 클래스에서 상속하므로 모든 형식은 Equals(Object), GetType()ToString()과 같은 해당 멤버를 상속합니다.Since all types in the managed type system inherit directly or indirectly from the Object class, all types inherit its members, such as Equals(Object), GetType(), and ToString(). 다음 예제에서는 Person 클래스를 정의하고, 두 개의 Person 개체를 인스턴스화하고, Person.Equals 메서드를 호출하여 두 개체가 같은지 여부를 확인합니다.The following example defines a Person class, instantiates two Person objects, and calls the Person.Equals method to determine whether the two objects are equal. 그러나 Equals 메서드는 Person 클래스에서 정의되지 않고 Object에서 상속됩니다.The Equals method, however, is not defined in the Person class; it is inherited from Object.

using System;

public class Person
{
   public String FirstName;
}

public class Example
{
   public static void Main()
   {
      var p1 = new Person();
      p1.FirstName = "John";
      var p2 = new Person();
      p2.FirstName = "John";
      Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
   }
}
// The example displays the following output:
//      p1 = p2: False

형식은 override 키워드를 사용하고 재정의된 메서드에 대한 구현을 제공하여 상속된 멤버를 재정의할 수 있습니다.Types can override inherited members by using the override keyword and providing an implementation for the overridden method. 메서드 시그니처는 재정의된 메서드의 시그니처와 같아야 합니다.The method signature must be the same as that of the overridden method. 다음 예제는 Equals(Object) 메서드를 재정의한다는 점을 제외하고 이전 예제와 비슷합니다.The following example is like the previous one, except that it overrides the Equals(Object) method. 또한 두 메서드가 일치하는 결과를 제공하기 때문에 GetHashCode() 메서드를 재정의합니다.(It also overrides the GetHashCode() method, since the two methods are intended to provide consistent results.)

using System;

public class Person
{
   public String FirstName;

   public override bool Equals(object obj)
   {
      var p2 = obj as Person;
      if (p2 == null)
         return false;
      else
         return FirstName.Equals(p2.FirstName);
   }

   public override int GetHashCode()
   {
      return FirstName.GetHashCode();
   }
}

public class Example
{
   public static void Main()
   {
      var p1 = new Person();
      p1.FirstName = "John";
      var p2 = new Person();
      p2.FirstName = "John";
      Console.WriteLine("p1 = p2: {0}", p1.Equals(p2));
   }
}
// The example displays the following output:
//      p1 = p2: True

매개 변수 전달Passing parameters

C#의 형식은 값 형식 또는 참조 형식 입니다.Types in C# are either value types or reference types. 기본 제공 값 형식의 목록은 형식을 참조하세요.For a list of built-in value types, see Types. 기본적으로, 값 형식과 참조 형식은 둘 다 값으로 메서드에 전달됩니다.By default, both value types and reference types are passed to a method by value.

값으로 매개 변수 전달Passing parameters by value

값 형식이 값으로 메서드에 전달되는 경우 개체 자체가 아니라 개체의 복사본이 메서드에 전달됩니다.When a value type is passed to a method by value, a copy of the object instead of the object itself is passed to the method. 따라서 제어가 호출자로 반환될 때 호출된 메서드의 개체 변경 내용은 원래 개체에 영향을 주지 않습니다.Therefore, changes to the object in the called method have no effect on the original object when control returns to the caller.

다음 예제에서는 값 형식을 값으로 메서드에 전달하며, 호출된 메서드는 값 형식의 값을 변경하려고 합니다.The following example passes a value type to a method by value, and the called method attempts to change the value type's value. 값 형식인 int 형식의 변수를 정의하고, 해당 값을 20으로 초기화한 다음 ModifyValue라는 메서드에 전달하면 이 메서드가 변수의 값을 30으로 변경합니다.It defines a variable of type int, which is a value type, initializes its value to 20, and passes it to a method named ModifyValue that changes the variable's value to 30. 그러나 메서드가 반환될 때는 변수의 값이 변경되지 않습니다.When the method returns, however, the variable's value remains unchanged.

using System;

public class Example
{
   public static void Main()
   {
      int value = 20;
      Console.WriteLine("In Main, value = {0}", value);
      ModifyValue(value);
      Console.WriteLine("Back in Main, value = {0}", value);
   }

   static void ModifyValue(int i)
   {
      i = 30;
      Console.WriteLine("In ModifyValue, parameter value = {0}", i);
      return;
   }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 20

참조 형식의 개체가 메서드에 값으로 전달되는 경우 개체에 대한 참조가 값으로 전달됩니다.When an object of a reference type is passed to a method by value, a reference to the object is passed by value. 즉, 메서드는 개체 자체가 아니라 개체의 위치를 나타내는 인수를 수신합니다.That is, the method receives not the object itself, but an argument that indicates the location of the object. 이 참조를 사용하여 개체의 멤버를 변경하는 경우 제어가 호출하는 메서드로 반환될 때 변경 내용이 개체에 반영됩니다.If you change a member of the object by using this reference, the change is reflected in the object when control returns to the calling method. 그러나 메서드에 전달되는 개체를 바꾸면 제어가 호출자로 반환될 때 원래 개체에 영향을 주지 않습니다.However, replacing the object passed to the method has no effect on the original object when control returns to the caller.

다음 예제에서는 SampleRefType이라는 클래스(참조 형식)를 정의합니다.The following example defines a class (which is a reference type) named SampleRefType. SampleRefType 개체를 인스턴스화하고, 해당 value 필드에 44를 할당한 다음 개체를 ModifyObject 메서드에 전달합니다.It instantiates a SampleRefType object, assigns 44 to its value field, and passes the object to the ModifyObject method. 이 예제는 인수를 값으로 메서드에 전달한다는 점에서 기본적으로 이전 예제와 같은 작업을 수행합니다.This example does essentially the same thing as the previous example -- it passes an argument by value to a method. 그러나 참조 형식이 사용되므로 결과가 다릅니다.But because a reference type is used, the result is different. 예제의 출력과 같이 ModifyObject에서 obj.value 필드에 대해 수정한 내용으로 인해 Main 메서드에서 rt 인수의 value 필드도 33으로 변경됩니다.The modification that is made in ModifyObject to the obj.value field also changes the value field of the argument, rt, in the Main method to 33, as the output from the example shows.

using System;

public class SampleRefType
{
    public int value;
}

public class Example
{
    public static void Main()
    {
        var rt = new SampleRefType();
        rt.value = 44;
        ModifyObject(rt);
        Console.WriteLine(rt.value);
    }

    static void ModifyObject(SampleRefType obj)
    {
        obj.value = 33;
    }
}

참조로 매개 변수 전달Passing parameters by reference

메서드의 인수 값을 변경하고 제어가 호출하는 메서드로 반환될 때 해당 변경 내용을 반영하려는 경우 참조로 매개 변수를 전달합니다.You pass a parameter by reference when you want to change the value of an argument in a method and want to reflect that change when control returns to the calling method. 참조로 매개 변수를 전달하려면 ref 또는 out 키워드를 사용합니다.To pass a parameter by reference, you use the ref or out keyword. 복사를 방지하지만 여전히 in 키워드를 사용하여 수정을 방지하도록 참조로 값을 전달할 수도 있습니다.You can also pass a value by reference to avoid copying but still prevent modifications using the in keyword.

다음 예제는 값이 참조로 ModifyValue 메서드에 전달된다는 점을 제외하고 이전 예제와 동일합니다.The following example is identical to the previous one, except the value is passed by reference to the ModifyValue method. ModifyValue 메서드에서 매개 변수의 값을 수정하면 제어가 호출자로 반환될 때 값의 변경 내용이 반영됩니다.When the value of the parameter is modified in the ModifyValue method, the change in value is reflected when control returns to the caller.

using System;

public class Example
{
   public static void Main()
   {
      int value = 20;
      Console.WriteLine("In Main, value = {0}", value);
      ModifyValue(ref value);
      Console.WriteLine("Back in Main, value = {0}", value);
   }

   static void ModifyValue(ref int i)
   {
      i = 30;
      Console.WriteLine("In ModifyValue, parameter value = {0}", i);
      return;
   }
}
// The example displays the following output:
//      In Main, value = 20
//      In ModifyValue, parameter value = 30
//      Back in Main, value = 30

by ref 매개 변수를 사용하는 일반적인 패턴은 변수 값의 교환을 포함합니다.A common pattern that uses by ref parameters involves swapping the values of variables. 두 개의 변수를 참조로 메서드에 전달하고 메서드가 해당 내용을 바꿉니다.You pass two variables to a method by reference, and the method swaps their contents. 다음 예제에서는 정수 값을 바꿉니다.The following example swaps integer values.

using System;

public class Example
{
   static void Main()
   {
      int i = 2, j = 3;
      System.Console.WriteLine("i = {0}  j = {1}" , i, j);

      Swap(ref i, ref j);

      System.Console.WriteLine("i = {0}  j = {1}" , i, j);
   }

   static void Swap(ref int x, ref int y)
   {
      int temp = x;
      x = y;
      y = temp;
   }
}
// The example displays the following output:
//      i = 2  j = 3
//      i = 3  j = 2

참조 형식 매개 변수를 전달하면 해당 개별 요소 또는 필드의 값이 아니라 참조 자체의 값을 변경할 수 있습니다.Passing a reference-type parameter allows you to change the value of the reference itself, rather than the value of its individual elements or fields.

매개 변수 배열Parameter arrays

경우에 따라 메서드의 인수 개수를 정확하게 지정하라는 요구 사항은 제한적입니다.Sometimes, the requirement that you specify the exact number of arguments to your method is restrictive. params 키워드를 사용하여 매개 변수를 매개 변수 배열로 지정하면 가변 개수의 인수로 메서드를 호출할 수 있습니다.By using the params keyword to indicate that a parameter is a parameter array, you allow your method to be called with a variable number of arguments. params 키워드로 태그가 지정된 매개 변수는 배열 형식이어야 하며, 메서드의 매개 변수 목록에서 마지막 매개 변수여야 합니다.The parameter tagged with the params keyword must be an array type, and it must be the last parameter in the method's parameter list.

그러면 호출자가 다음 네 가지 방법 중 하나로 메서드를 호출할 수 있습니다.A caller can then invoke the method in either of four ways:

  • 원하는 개수의 요소를 포함하는 적절한 형식의 배열 전달By passing an array of the appropriate type that contains the desired number of elements.
  • 적절한 형식의 개별 인수가 포함된 쉼표로 구분된 목록을 메서드에 전달By passing a comma-separated list of individual arguments of the appropriate type to the method.
  • null을 전달By passing null.
  • 매개 변수 배열에 인수 제공 안 함By not providing an argument to the parameter array.

다음 예제에서는 매개 변수 배열의 모든 모음을 반환하는 GetVowels 메서드를 정의합니다.The following example defines a method named GetVowels that returns all the vowels from a parameter array. Main 메서드는 해당 메서드를 호출하는 네 가지 방법을 모두 보여 줍니다.The Main method illustrates all four ways of invoking the method. 호출자가 params 한정자를 포함하는 매개 변수의 인수를 제공할 필요는 없습니다.Callers are not required to supply any arguments for parameters that include the params modifier. 이 경우 매개 변수는 빈 배열입니다.In that case, the parameter is an empty array.

using System;
using System.Linq;

class Example
{
    static void Main()
    {
        string fromArray = GetVowels(new[] { "apple", "banana", "pear" });
        Console.WriteLine($"Vowels from array: '{fromArray}'");

        string fromMultipleArguments = GetVowels("apple", "banana", "pear");
        Console.WriteLine($"Vowels from multiple arguments: '{fromMultipleArguments}'");
        
        string fromNull = GetVowels(null);
        Console.WriteLine($"Vowels from null: '{fromNull}'");

        string fromNoValue = GetVowels();
        Console.WriteLine($"Vowels from no value: '{fromNoValue}'");
    }

    static string GetVowels(params string[] input)
    {
        if (input == null || input.Length == 0)
        {
            return string.Empty;
        }

        var vowels = new char[] { 'A', 'E', 'I', 'O', 'U' };
        return string.Concat(
            input.SelectMany(
                word => word.Where(letter => vowels.Contains(char.ToUpper(letter)))));
    }
}

// The example displays the following output:
//     Vowels from array: 'aeaaaea'
//     Vowels from multiple arguments: 'aeaaaea'
//     Vowels from null: ''
//     Vowels from no value: ''

선택적 매개 변수 및 인수Optional parameters and arguments

메서드 정의에서 해당 매개 변수를 필수 또는 선택 사항으로 지정할 수 있습니다.A method definition can specify that its parameters are required or that they are optional. 기본적으로 매개 변수는 필수입니다.By default, parameters are required. 선택적 매개 변수는 메서드 정의에 매개 변수의 기본값을 포함하여 지정됩니다.Optional parameters are specified by including the parameter's default value in the method definition. 메서드를 호출할 때 선택적 매개 변수에 대한 인수가 제공되지 않은 경우 기본값이 대신 사용됩니다.When the method is called, if no argument is supplied for an optional parameter, the default value is used instead.

다음 종류의 식 중 하나로 매개 변수의 기본값을 할당해야 합니다.The parameter's default value must be assigned by one of the following kinds of expressions:

  • 리터럴 문자열이나 숫자와 같은 상수A constant, such as a literal string or number.
  • new ValType() 형태의 식. 여기서 ValType은 값 형식입니다.An expression of the form new ValType(), where ValType is a value type. 이 경우 형식의 실제 멤버가 아닌 값 형식의 매개 변수가 없는 암시적 생성자가 호출됩니다.Note that this invokes the value type's implicit parameterless constructor, which is not an actual member of the type.
  • default(ValType) 형태의 식. 여기서 ValType은 값 형식입니다.An expression of the form default(ValType), where ValType is a value type.

메서드에 필수 및 선택적 매개 변수가 둘 다 포함된 경우 선택적 매개 변수는 매개 변수 목록의 끝에서 모든 필수 매개 변수 다음에 정의됩니다.If a method includes both required and optional parameters, optional parameters are defined at the end of the parameter list, after all required parameters.

다음 예제에서는 필수 매개 변수 하나와 선택적 매개 변수 두 개가 있는 ExampleMethod 메서드를 정의합니다.The following example defines a method, ExampleMethod, that has one required and two optional parameters.

using System;

public class Options
{
   public void ExampleMethod(int required, int optionalInt = default(int),
                             string description = "Optional Description")
   {
      Console.WriteLine("{0}: {1} + {2} = {3}", description, required,
                        optionalInt, required + optionalInt);
   }
}

여러 선택적 인수가 있는 메서드를 위치 인수로 호출하는 경우 호출자가 첫 번째 매개 변수부터 인수가 제공되는 마지막 매개 변수까지 모든 선택적 매개 변수에 대한 인수를 제공해야 합니다.If a method with multiple optional arguments is invoked using positional arguments, the caller must supply an argument for all optional parameters from the first one to the last one for which an argument is supplied. 예를 들어 ExampleMethod 메서드에서 호출자가 description 매개 변수에 대한 인수를 제공하는 경우 optionalInt 매개 변수에 대한 인수도 제공해야 합니다.In the case of the ExampleMethod method, for example, if the caller supplies an argument for the description parameter, it must also supply one for the optionalInt parameter. opt.ExampleMethod(2, 2, "Addition of 2 and 2");는 유효한 메서드 호출이고, opt.ExampleMethod(2, , "Addition of 2 and 0");은 "인수가 없습니다." 컴파일러 오류를 생성합니다.opt.ExampleMethod(2, 2, "Addition of 2 and 2"); is a valid method call; opt.ExampleMethod(2, , "Addition of 2 and 0"); generates an "Argument missing" compiler error.

명명된 인수 또는 위치 인수와 명명된 인수의 조합을 사용하여 메서드를 호출하는 경우 호출자는 메서드 호출에서 마지막 위치 인수 뒤에 오는 모든 인수를 생략할 수 있습니다.If a method is called using named arguments or a combination of positional and named arguments, the caller can omit any arguments that follow the last positional argument in the method call.

다음 예제에서는 ExampleMethod 메서드를 세 번 호출합니다.The following example calls the ExampleMethod method three times. 처음 두 메서드 호출은 위치 인수를 사용합니다.The first two method calls use positional arguments. 첫 번째 호출은 선택적 인수를 둘 다 생략하고, 두 번째 호출은 마지막 인수를 생략합니다.The first omits both optional arguments, while the second omits the last argument. 세 번째 메서드 호출은 필수 매개 변수에 대한 위치 인수를 제공하지만 optionalInt 인수를 생략하고 명명된 인수를 사용하여 description 매개 변수에 값을 제공합니다.The third method call supplies a positional argument for the required parameter but uses a named argument to supply a value to the description parameter while omitting the optionalInt argument.

public class Example
{
   public static void Main()
   {
      var opt = new Options();
      opt.ExampleMethod(10);
      opt.ExampleMethod(10, 2);
      opt.ExampleMethod(12, description: "Addition with zero:");
   }
}
// The example displays the following output:
//      Optional Description: 10 + 0 = 10
//      Optional Description: 10 + 2 = 12
//      Addition with zero:: 12 + 0 = 12

선택적 매개 변수를 사용하면 오버로드 확인 또는 C# 컴파일러가 메서드 호출에서 호출해야 하는 특정 오버로드를 확인하는 방법이 다음과 같이 영향을 받습니다.The use of optional parameters affects overload resolution, or the way in which the C# compiler determines which particular overload should be invoked by a method call, as follows:

  • 메서드, 인덱서 또는 생성자는 해당 매개 변수가 각각 선택 사항이거나 이름 또는 위치로 호출하는 문의 단일 인수에 해당하고 이 인수를 매개 변수의 형식으로 변환할 수 있는 경우 실행 후보가 됩니다.A method, indexer, or constructor is a candidate for execution if each of its parameters either is optional or corresponds, by name or by position, to a single argument in the calling statement, and that argument can be converted to the type of the parameter.
  • 둘 이상의 인증서가 있으면 기본 설정 변환에 대한 오버로드 확인 규칙이 명시적으로 지정된 인수에 적용됩니다.If more than one candidate is found, overload resolution rules for preferred conversions are applied to the arguments that are explicitly specified. 선택적 매개 변수에 대해 생략된 인수는 무시됩니다.Omitted arguments for optional parameters are ignored.
  • 두 후보가 똑같이 정상이라고 판단되는 경우 기본적으로 호출에서 인수가 생략된 선택적 매개 변수가 없는 후보가 설정됩니다.If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. 이는 매개 변수가 적은 후보에 대한 오버로드 확인에서 일반적인 기본 설정의 결과입니다.This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.

반환 값Return values

메서드는 호출자에 값을 반환할 수 있습니다.Methods can return a value to the caller. 메서드 이름 앞에 나열된 반환 형식이 void가 아니면 메서드는 return 키워드를 사용하여 값을 반환할 수 있습니다.If the return type (the type listed before the method name) is not void, the method can return the value by using the return keyword. return 키워드에 이어 반환 형식과 일치하는 변수, 상수 또는 식을 포함하는 문은 메서드 호출자에 값을 반환합니다.A statement with the return keyword followed by a variable, constant, or expression that matches the return type will return that value to the method caller. return 키워드를 사용하여 값을 반환하려면 void가 아닌 반환 값을 포함한 메서드가 필요합니다.Methods with a non-void return type are required to use the return keyword to return a value. return 키워드는 메서드 실행을 중지합니다.The return keyword also stops the execution of the method.

반환 형식이 void이면 값이 없는 return 문을 사용하여 메서드 실행을 중지할 수 있습니다.If the return type is void, a return statement without a value is still useful to stop the execution of the method. return 키워드를 사용하지 않으면 메서드는 코드 블록 끝에 도달할 때 실행을 중지합니다.Without the return keyword, the method will stop executing when it reaches the end of the code block.

예를 들어 이들 두 메서드에서는 return 키워드를 사용하여 정수를 반환합니다.For example, these two methods use the return keyword to return integers:

class SimpleMath
{
    public int AddTwoNumbers(int number1, int number2)
    {
        return number1 + number2;
    }

    public int SquareANumber(int number)
    {
        return number * number;
    }
}

메서드에서 반환된 값을 사용하려면 호출하는 메서드에서 같은 형식의 값으로 충분한 모든 경우에 메서드 호출 자체를 사용하면 됩니다.To use a value returned from a method, the calling method can use the method call itself anywhere a value of the same type would be sufficient. 반환 값을 변수에 할당할 수도 있습니다.You can also assign the return value to a variable. 예를 들어 다음 두 코드 예제에서는 같은 목표를 달성합니다.For example, the following two code examples accomplish the same goal:

int result = obj.AddTwoNumbers(1, 2);
result = obj.SquareANumber(result);
// The result is 9.
Console.WriteLine(result);
result = obj.SquareANumber(obj.AddTwoNumbers(1, 2));
// The result is 9.
Console.WriteLine(result);

지역 변수(이 경우 result)를 사용하여 값을 저장하는 것은 선택 사항입니다.Using a local variable, in this case, result, to store a value is optional. 코드의 가독성에 도움이 될 수 있고 전체 메서드 범위에 대해 인수의 원래 값을 저장해야 할 경우 필요할 수도 있습니다.It may help the readability of the code, or it may be necessary if you need to store the original value of the argument for the entire scope of the method.

메서드에서 둘 이상의 값을 반환하려는 경우도 있습니다.Sometimes, you want your method to return more than a single value. C# 7.0부터 튜플 형식튜플 리터럴 을 사용하면 이 작업을 쉽게 수행할 수 있습니다.Starting with C# 7.0, you can do this easily by using tuple types and tuple literals. 튜플 형식은 튜플 요소의 데이터 형식을 정의합니다.The tuple type defines the data types of the tuple's elements. 튜플 리터럴은 반환된 튜플의 실제 값을 제공합니다.Tuple literals provide the actual values of the returned tuple. 다음 예제에서 (string, string, string, int)GetPersonalInfo 메서드에서 반환되는 튜플 형식을 정의합니다.In the following example, (string, string, string, int) defines the tuple type that is returned by the GetPersonalInfo method. (per.FirstName, per.MiddleName, per.LastName, per.Age) 식은 튜플 리터럴입니다. 메서드는 PersonInfo 개체와 함께 이름, 중간 이름 및 성을 반환합니다.The expression (per.FirstName, per.MiddleName, per.LastName, per.Age) is the tuple literal; the method returns the first, middle, and last name, along with the age, of a PersonInfo object.

public (string, string, string, int) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

호출자는 반환된 튜플을 코드에서 다음과 같이 사용할 수 있습니다.The caller can then consume the returned tuple with code like the following:

var person = GetPersonalInfo("111111111")
Console.WriteLine($"{person.Item1} {person.Item3}: age = {person.Item4}");

튜플 형식 정의의 튜플 요소에 이름을 할당할 수도 있습니다.Names can also be assigned to the tuple elements in the tuple type definition. 다음 예제에서는 명명된 요소를 사용하는 GetPersonalInfo 메서드의 대체 버전을 보여 줍니다.The following example shows an alternate version of the GetPersonalInfo method that uses named elements:

public (string FName, string MName, string LName, int Age) GetPersonalInfo(string id)
{
    PersonInfo per = PersonInfo.RetrieveInfoById(id);
    return (per.FirstName, per.MiddleName, per.LastName, per.Age);
}

GetPersonInfo 메서드에 대한 이전 호출을 다음과 같이 수정할 수 있습니다.The previous call to the GetPersonInfo method can then be modified as follows:

var person = GetPersonalInfo("111111111");
Console.WriteLine($"{person.FName} {person.LName}: age = {person.Age}");

메서드에 배열이 인수로 전달되고 메서드가 개별 요소의 값을 수정하는 경우 값의 스타일 또는 기능 흐름 개선을 위해 메서드에서 배열을 반환하도록 선택할 수도 있지만 필수는 아닙니다.If a method is passed an array as an argument and modifies the value of individual elements, it is not necessary for the method to return the array, although you may choose to do so for good style or functional flow of values. 이는 C#에서 모든 참조 형식을 값으로 전달하고 배열 참조의 값이 배열에 대한 포인터이기 때문입니다.This is because C# passes all reference types by value, and the value of an array reference is the pointer to the array. 다음 예제에서는 DoubleValues 메서드에서 수행한 values 배열 내용의 변경 사항을 배열에 대한 참조가 있는 모든 코드에서 관찰할 수 있습니다.In the following example, changes to the contents of the values array that are made in the DoubleValues method are observable by any code that has a reference to the array.


using System;

public class Example
{
   static void Main(string[] args)
   {
      int[] values = { 2, 4, 6, 8 };
      DoubleValues(values);
      foreach (var value in values)
         Console.Write("{0}  ", value);
   }

   public static void DoubleValues(int[] arr)
   {
      for (int ctr = 0; ctr <= arr.GetUpperBound(0); ctr++)
         arr[ctr] = arr[ctr] * 2;
   }
}
// The example displays the following output:
//       4  8  12  16

확장 메서드Extension methods

일반적으로 기존 형식에 메서드를 추가하는 방법에는 다음 두 가지가 있습니다.Ordinarily, there are two ways to add a method to an existing type:

  • 해당 형식에 대한 소스 코드를 수정합니다.Modify the source code for that type. 물론, 형식의 소스 코드를 소유하지 않은 경우에는 이 작업을 수행할 수 없습니다.You cannot do this, of course, if you do not own the type's source code. 이는 메서드를 지원하기 위해 전용 데이터 필드를 추가하는 경우에도 주요 변경 내용이 됩니다.And this becomes a breaking change if you also add any private data fields to support the method.
  • 파생 클래스에서 새 메서드를 정의합니다.Define the new method in a derived class. 구조체, 열거형 등의 다른 형식에 대해 상속을 사용하여 이러한 방식으로 메서드를 추가할 수는 없습니다.A method cannot be added in this way using inheritance for other types, such as structures and enumerations. 봉인 클래스에 메서드를 "추가"하는 데 사용할 수도 없습니다.Nor can it be used to "add" a method to a sealed class.

확장 메서드를 사용하면 형식 자체를 수정하거나 상속된 형식에서 새 메서드를 구현하지 않고 기존 형식에 메서드를 "추가"할 수 있습니다.Extension methods let you "add" a method to an existing type without modifying the type itself or implementing the new method in an inherited type. 또한 확장 메서드는 확장하는 형식과 동일한 어셈블리에 있지 않아도 됩니다.The extension method also does not have to reside in the same assembly as the type it extends. 형식의 정의된 멤버인 것처럼 확장 메서드를 호출합니다.You call an extension method as if it were a defined member of a type.

자세한 내용은 확장 메서드를 참조하세요.For more information, see Extension Methods.

비동기 메서드Async Methods

비동기 기능을 사용하면 명시적 콜백을 사용하거나 수동으로 여러 메서드 또는 람다 식에 코드를 분할하지 않고도 비동기 메서드를 호출할 수 있습니다.By using the async feature, you can invoke asynchronous methods without using explicit callbacks or manually splitting your code across multiple methods or lambda expressions.

메서드에 async 한정자를 표시하면 메서드에서 await 연산자를 사용할 수 있습니다.If you mark a method with the async modifier, you can use the await operator in the method. 제어가 비동기 메서드의 await 식에 도달하면 대기된 작업이 완료되지 않은 경우 제어가 호출자로 반환되고, 대기된 작업이 완료될 때까지 await 키워드가 있는 메서드의 진행이 일시 중단됩니다.When control reaches an await expression in the async method, control returns to the caller if the awaited task is not completed, and progress in the method with the await keyword is suspended until the awaited task completes. 작업이 완료되면 메서드가 실행이 다시 시작될 수 있습니다.When the task is complete, execution can resume in the method.

참고

비동기 메서드는 아직 완료되지 않은 첫 번째 대기된 개체를 검색할 때나 비동기 메서드의 끝에 도달할 때 중에서 먼저 발생하는 시점에 호출자에게 반환됩니다.An async method returns to the caller when either it encounters the first awaited object that's not yet complete or it gets to the end of the async method, whichever occurs first.

비동기 메서드의 반환 형식은 Task<TResult>, Task 또는 void일 수 있습니다.An async method can have a return type of Task<TResult>, Task, or void. void 반환 형식은 기본적으로 void 반환 형식이 필요할 때 이벤트 처리기를 정의하는 데 사용됩니다.The void return type is used primarily to define event handlers, where a void return type is required. void를 반환하는 비동기 메서드는 대기할 수 없고 void를 반환하는 메서드의 호출자는 메서드가 throw하는 예외를 catch할 수 없습니다.An async method that returns void can't be awaited, and the caller of a void-returning method can't catch exceptions that the method throws. C# 7.0부터 비동기 메서드에는 작업과 유사한 반환 형식이 있을 수 있습니다.Starting with C# 7.0, an async method can have any task-like return type.

다음 예제에서 DelayAsync는 정수를 반환하는 return 문을 포함하는 비동기 메서드입니다.In the following example, DelayAsync is an async method that has a return statement that returns an integer. 비동기 메서드이기 때문에 해당 메서드 선언의 반환 형식은 Task<int>여야 합니다.Because it is an async method, its method declaration must have a return type of Task<int>. 반환 형식이 Task<int>이므로 DoSomethingAsyncawait 식 계산에서 다음 int result = await delayTask 문과 같이 정수가 생성됩니다.Because the return type is Task<int>, the evaluation of the await expression in DoSomethingAsync produces an integer, as the following int result = await delayTask statement demonstrates.

using System;
using System.Threading.Tasks;

class Program
{
    static Task Main() => DoSomethingAsync();

    static async Task DoSomethingAsync()
    {
        Task<int> delayTask = DelayAsync();
        int result = await delayTask;

        // The previous two statements may be combined into
        // the following statement.
        //int result = await DelayAsync();

        Console.WriteLine($"Result: {result}");
    }

    static async Task<int> DelayAsync()
    {
        await Task.Delay(100);
        return 5;
    }
}
// Example output:
//   Result: 5

비동기 메서드는 모든 in, ref 또는 out 매개 변수를 선언할 수 없지만, 이러한 매개 변수가 있는 메서드를 호출할 수는 있습니다.An async method can't declare any in, ref, or out parameters, but it can call methods that have such parameters.

비동기 메서드에 관한 자세한 내용은 async 및 await를 사용한 비동기 프로그래밍비동기 반환 형식을 참조하세요.For more information about async methods, see Asynchronous programming with async and await and Async return types.

식 본문 멤버Expression-bodied members

일반적으로 식의 결과와 함께 바로 반환되거나 단일 문이 메서드 본문으로 포함된 메서드 정의가 있습니다.It is common to have method definitions that simply return immediately with the result of an expression, or that have a single statement as the body of the method. =>를 사용하여 해당 메서드를 속성을 정의하기 위한 구문 바로 가기는 다음과 같습니다.There is a syntax shortcut for defining such methods using =>:

public Point Move(int dx, int dy) => new Point(x + dx, y + dy);
public void Print() => Console.WriteLine(First + " " + Last);
// Works with operators, properties, and indexers too.
public static Complex operator +(Complex a, Complex b) => a.Add(b);
public string Name => First + " " + Last;
public Customer this[long id] => store.LookupCustomer(id);

메서드가 void를 반환하거나 비동기 메서드이면 메서드 본문은 문 식이어야 합니다(람다에서와 같음).If the method returns void or is an async method, the body of the method must be a statement expression (same as with lambdas). 속성 및 인덱서의 경우 읽기 전용이어야 하며, get 접근자 키워드를 사용하지 않습니다.For properties and indexers, they must be read-only, and you do not use the get accessor keyword.

IteratorsIterators

반복기는 배열 목록과 같은 컬렉션에 대해 사용자 지정 반복을 수행합니다.An iterator performs a custom iteration over a collection, such as a list or an array. 반복기는 yield return 문을 사용하여 각 요소를 따로따로 반환할 수 있습니다.An iterator uses the yield return statement to return each element one at a time. yield return 문에 도달하면 호출자가 시퀀스의 다음 요소를 요청할 수 있도록 현재 위치가 기억됩니다.When a yield return statement is reached, the current location is remembered so that the caller can request the next element in the sequence.

반복기의 반환 형식은 IEnumerable, IEnumerable<T>, IEnumerator 또는 IEnumerator<T>일 수 있습니다.The return type of an iterator can be IEnumerable, IEnumerable<T>, IEnumerator, or IEnumerator<T>.

자세한 내용은 반복기를 참조하세요.For more information, see Iterators.

참고 항목See also