메서드는 일련의 문을 포함하는 코드 블록입니다. 프로그램을 통해 메서드를 호출하고 필요한 메서드 인수를 지정하여 문을 실행합니다. C#에서는 실행된 모든 명령이 메서드의 컨텍스트에서 수행됩니다.
이 Main
메서드는 모든 C# 애플리케이션의 진입점이며 프로그램이 시작될 때 CLR(공용 언어 런타임)에 의해 호출됩니다.
최상위 문을Main
사용하는 애플리케이션에서 메서드는 컴파일러에 의해 생성되고 모든 최상위 문을 포함합니다.
비고
이 문서에서는 명명된 메서드에 대해 설명합니다. 무명 기능에 대한 자세한 내용은 람다 식을 참조하세요.
메서드 서명
메서드는 클래스, 구조체, 또는 인터페이스에서 선언되며, public
또는 private
와 같은 접근 수준, abstract
또는 sealed
와 같은 선택적 한정자, 반환 값, 메서드 이름 및 메서드 매개 변수를 지정하여 설명됩니다. 이러한 부분은 메서드의 서명입니다.
중요합니다
메서드의 반환 값은 메서드 오버로드를 위한 메서드 서명의 파트가 아닙니다. 그러나 대리자와 대리자가 가리키는 메서드 간의 호환성을 결정할 경우에는 메서드 서명의 부분입니다.
메서드 매개 변수는 괄호로 묶고 쉼표로 구분됩니다. 빈 괄호는 메서드에 매개 변수가 필요하지 않음을 나타냅니다. 이 클래스에는 다음 네 가지 메서드가 포함됩니다.
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 must implement this.
public abstract double GetTopSpeed();
}
메서드 접근
개체에서 메서드를 호출하는 것은 필드에 액세스하는 것과 같습니다. 개체 이름 뒤 마침표, 메서드 이름 및 괄호를 추가합니다. 인수는 괄호 안에 나열되고 쉼표로 구분됩니다. 따라서 다음 예제와 같이 클래스의 Motorcycle
메서드를 호출할 수 있습니다.
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 {speed}");
}
}
메서드 매개 변수 및 인수
메서드 정의는 필요한 모든 매개 변수의 이름 및 형식을 지정합니다. 코드를 호출할 때 메서드는 각 매개 변수에 대한 인수라는 구체적인 값을 제공합니다. 인수는 매개 변수 형식과 호환되어야 하지만 호출 코드에 사용된 인수 이름(있는 경우)은 메서드에 정의된 매개 변수와 같을 필요가 없습니다. 다음은 그 예입니다.
public void Caller()
{
int numA = 4;
// Call with an int variable.
int productA = Square(numA);
int numB = 32;
// Call with another int variable.
int productB = Square(numB);
// Call with an integer literal.
int productC = Square(12);
// Call with an expression that evaluates to int.
productC = Square(productA * 3);
}
int Square(int i)
{
// Store input argument in a local variable.
int input = i;
return input * input;
}
참조로 전달 대 값으로 전달
기본적으로 값 형식 의 인스턴스가 메서드에 전달되면 인스턴스 자체가 아니라 해당 복사본이 전달됩니다. 따라서 인수를 변경해도 호출 메서드의 원래 인스턴스에는 영향을 주지 않습니다. 참조로 값 형식 인스턴스를 전달하려면 키워드를 ref
사용합니다. 자세한 내용은 Value-Type 매개 변수 전달을 참조하세요.
참조 형식의 개체가 메서드에 전달되면 개체에 대한 참조가 전달됩니다. 즉, 메서드는 개체 자체가 아니라 개체의 위치를 나타내는 인수를 받습니다. 이 참조를 사용하여 개체의 멤버를 변경하는 경우 값으로 개체를 전달하는 경우에도 변경 내용이 호출 메서드의 인수에 반영됩니다.
다음 예제와 같이 키워드를 class
사용하여 참조 형식을 만듭니다.
public class SampleRefType
{
public int value;
}
이제 이 형식을 기반으로 하는 개체를 메서드에 전달하면 개체에 대한 참조가 전달됩니다. 다음 예제에서는 메서드ModifyObject
에 형식 SampleRefType
의 개체를 전달합니다.
public static void TestRefType()
{
SampleRefType rt = new SampleRefType();
rt.value = 44;
ModifyObject(rt);
Console.WriteLine(rt.value);
}
static void ModifyObject(SampleRefType obj)
{
obj.value = 33;
}
이 예제는 값으로 인수를 메서드에 전달한다는 이전 예제와 기본적으로 동일한 작업을 수행합니다. 그러나 참조 형식이 사용되므로 결과가 다릅니다.
ModifyObject
에서 매개변수 obj
의 value
필드를 수정하면, TestRefType
메서드의 인수 rt
의 value
필드도 변경됩니다. 이 메서드는 TestRefType
33을 출력으로 표시합니다.
참조 및 값으로 참조 형식을 전달하는 방법에 대한 자세한 내용은 Reference-Type 매개 변수 및 참조 형식 전달을 참조하세요.
반환 값
메서드는 호출자에 값을 반환할 수 있습니다. 반환 형식(메서드 이름 앞에 나열된 형식)이 아닌 void
경우 메서드는 문을 사용하여 값을 반환할 return
수 있습니다. 키워드와 return
반환 형식과 일치하는 값이 있는 문은 해당 값을 메서드 호출자에게 반환합니다.
값 또는 참조를 통해 호출자에게 값을 반환할 수 있습니다. 메서드 서명에서 ref
키워드를 사용하고 각 return
키워드 뒤에 ref
가 오는 경우 값은 참조로 호출자에게 반환됩니다. 예를 들어 다음 메서드 시그니처 및 return 문은 메서드가 호출자에 대한 참조로 명명된 estDistance
변수를 반환함을 나타냅니다.
public ref double GetEstimatedDistance()
{
return ref estDistance;
}
return
키워드는 메서드 실행을 중지합니다. 반환 형식이 void
이면 값이 없는 return
문을 사용하여 메서드 실행을 중지할 수 있습니다. 키워드가 return
없으면 메서드가 코드 블록의 끝에 도달하면 실행이 중지됩니다. 값을 반환하려면 void가 아닌 반환 형식의 메서드가 키워드를 return
사용해야 합니다. 예를 들어 이들 두 메서드에서는 return
키워드를 사용하여 정수를 반환합니다.
class SimpleMath
{
public int AddTwoNumbers(int number1, int number2)
{
return number1 + number2;
}
public int SquareANumber(int number)
{
return number * number;
}
}
메서드에서 반환된 값을 사용하기 위해 호출 메서드는 동일한 형식의 값으로 충분할 경우 메서드 호출 자체를 사용할 수 있습니다. 반환 값을 변수에 할당할 수도 있습니다. 예를 들어 다음 두 코드 예제는 동일한 목표를 달성합니다.
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
지역 변수를 사용하여 값을 저장하는 것은 선택 사항입니다. 코드의 가독성에 도움이 되거나 메서드의 전체 범위에 대한 인수의 원래 값을 저장해야 하는 경우 필요할 수 있습니다.
메서드에서 참조로 반환된 값을 사용하려면 해당 값을 수정하려는 경우 ref 지역 변수를 선언해야 합니다. 예를 들어 메서드가 Planet.GetEstimatedDistance
참조로 Double 값을 반환하는 경우 다음과 같은 코드를 사용하여 참조 지역 변수로 정의할 수 있습니다.
ref double distance = ref Planet.GetEstimatedDistance();
메서드 M
에서 다차원 배열을 반환합니다. 호출 함수가 배열을 전달한 M
경우에는 배열의 내용을 수정할 필요가 없습니다. 좋은 스타일이나 기능적 값 흐름을 위해 결과 배열 M
을 반환할 수 있지만 C#이 모든 참조 형식을 값으로 전달하고 배열 참조의 값이 배열에 대한 포인터이므로 필요하지 않습니다. 메서드 M
에서 배열 내용에 대한 변경 내용은 다음 예제와 같이 배열에 대한 참조가 있는 모든 코드에서 관찰할 수 있습니다.
static void Main(string[] args)
{
int[,] matrix = new int[2, 2];
FillMatrix(matrix);
// matrix is now full of -1
}
public static void FillMatrix(int[,] matrix)
{
for (int i = 0; i < matrix.GetLength(0); i++)
{
for (int j = 0; j < matrix.GetLength(1); j++)
{
matrix[i, j] = -1;
}
}
}
비동기 메서드
비동기 기능을 사용하면 명시적 콜백을 사용하거나 수동으로 여러 메서드 또는 람다 식에 코드를 분할하지 않고도 비동기 메서드를 호출할 수 있습니다.
메서드에 async 한정자를 표시하면 메서드에서 await 연산자를 사용할 수 있습니다. 컨트롤이 비동기 메서드의 await 식에 도달하면 컨트롤이 호출자로 반환되고 대기 중인 작업이 완료될 때까지 메서드의 진행률이 일시 중단됩니다. 작업이 완료되면 메서드가 실행이 다시 시작될 수 있습니다.
비고
비동기 메서드는 아직 완료되지 않은 첫 번째 대기된 개체를 검색할 때나 비동기 메서드의 끝에 도달할 때 중에서 먼저 발생하는 시점에 호출자에게 반환됩니다.
비동기 메서드는 일반적으로 반환 형식인 Task<TResult>또는 TaskIAsyncEnumerable<T>void
.
void
반환 형식은 기본적으로 void
반환 형식이 필요할 때 이벤트 처리기를 정의하는 데 사용됩니다.
void
를 반환하는 비동기 메서드는 대기할 수 없으며, void를 반환하는 메서드의 호출자는 메서드가 던지는 예외를 catch할 수 없습니다. 비동기 메서드에는 작업과 유사한 반환 형식이 있을 수 있습니다.
다음 예제 DelayAsync
에서는 반환 형식 Task<TResult>이 있는 비동기 메서드입니다.
DelayAsync
에는 정수가 return
반환되는 문이 있습니다. 따라서 메서드 선언에는 DelayAsync
반환 형식 Task<int>
이 있어야 합니다.
Task<int>
가 반환 형식이기 때문에 DoSomethingAsync
문에서 보여주는 대로 await
표현식의 계산 결과는 정수로 생성됩니다int result = await delayTask
.
이 Main
메서드는 반환 형식이 있는 비동기 메서드의 Task예입니다.
DoSomethingAsync
메서드로 이동한 후, 한 줄로 표현하기 때문에 async
및 await
키워드를 생략할 수 있습니다.
DoSomethingAsync
가 비동기 메서드이므로, DoSomethingAsync
호출에 대한 태스크는 await DoSomethingAsync();
와 같이 대기되어야 합니다.
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
비동기 메서드는 ref 또는 out 매개 변수를 선언할 수 없지만 이러한 매개 변수가 있는 메서드를 호출할 수 있습니다.
비동기 메서드에 관한 자세한 내용은 async 및 await를 사용한 비동기 프로그래밍 및 비동기 반환 형식을 참조하세요.
표현식 본문 정의
식의 결과로 즉시 반환하거나 단일 문을 메서드 본문으로 포함하는 메서드 정의가 있는 것이 일반적입니다. 다음을 사용하여 =>
이러한 메서드를 정의하기 위한 구문 바로 가기가 있습니다.
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
되거나 비동기 메서드인 경우 메서드의 본문은 문 식이어야 합니다(람다와 동일). 속성 및 인덱서의 경우 읽기 전용이어야 하며 접근자 키워드를 get
사용하지 않습니다.
반복기
반복기는 배열 목록과 같은 컬렉션에 대해 사용자 지정 반복을 수행합니다. 반복기는 yield return 문을 사용하여 각 요소를 따로따로 반환할 수 있습니다. 명령문 yield return
에 도달하면 코드의 현재 위치가 저장됩니다. 다음에 반복기가 호출될 때 해당 위치에서 실행이 다시 시작됩니다.
foreach 문을 사용하여 클라이언트 코드에서 반복기를 호출합니다.
반복기의 반환 형식은 IEnumerable, IEnumerable<T>, IAsyncEnumerable<T>, IEnumerator 또는 IEnumerator<T>일 수 있습니다.
자세한 내용은 반복기를 참조하세요.
C# 언어 사양
자세한 내용은 C# 언어 사양을 참조하세요. 언어 사양은 C# 구문 및 사용의 최종 소스입니다.
참고하십시오
.NET