Partial 클래스 및 메서드(C# 프로그래밍 가이드)
클래스나 구조체, 인터페이스 또는 메서드의 정의를 둘 이상의 소스 파일로 분할할 수 있습니다. 각 소스 파일에는 형식이나 메서드 정의 섹션이 들어 있고 이 모든 부분은 응용 프로그램을 컴파일할 때 결합됩니다.
Partial 클래스
클래스 정의는 다음과 같은 여러 가지 상황에서 분할할 수 있습니다.
대규모 프로젝트를 진행하는 경우 클래스를 개별 파일로 분할하면 여러 프로그래머가 동시에 작업을 수행할 수 있습니다.
자동으로 생성된 소스를 사용하여 작업하는 경우 소스 파일을 다시 만들지 않고도 클래스에 코드를 추가할 수 있습니다. Visual Studio에서는 Windows Forms, 웹 서비스 래퍼 코드 등을 만들 때 이러한 방식을 사용합니다. 따라서 Visual Studio에서 자동으로 만든 파일을 수정할 필요 없이 이러한 클래스를 사용하는 코드를 만들 수 있습니다.
클래스 정의를 분할하려면 다음과 같이 partial 키워드 한정자를 사용합니다.
public partial class Employee
{
public void DoWork()
{
}
}
public partial class Employee
{
public void GoToLunch()
{
}
}
partial 키워드는 클래스, 구조체 또는 인터페이스의 다른 부분을 네임스페이스 안에서 정의할 수 있음을 나타냅니다. 모든 부분에 partial 키워드를 사용해야 합니다. 최종 형식을 생성하려면 컴파일할 때 모든 부분을 사용할 수 있어야 합니다. 모든 부분은 public, private 등과 같이 액세스 가능성이 동일해야 합니다.
부분이 추상으로 선언되면 전체 형식이 추상으로 간주됩니다. 부분이 봉인으로 선언되면 전체 형식이 봉인으로 간주됩니다. 부분이 기본 형식으로 선언되면 전체 형식이 해당 클래스를 상속합니다.
기본 클래스를 지정하는 모든 부분이 일치해야 하지만 기본 클래스를 생략하는 부분에서도 기본 형식을 상속합니다. 부분은 서로 다른 기본 인터페이스를 지정할 수 있으며 이 경우 최종 형식에는 모든 partial 선언에 나열된 모든 인터페이스가 구현됩니다. partial 정의에 선언된 모든 클래스, 구조체 또는 인터페이스 멤버를 다른 모든 부분에 사용할 수 있습니다. 최종 형식은 컴파일 타임에 모든 부분의 조합이 됩니다.
참고
대리자나 열거형 선언에는 partial 한정자를 사용할 수 없습니다.
다음 예제에서는 중첩 형식을 포함하는 형식 자체가 partial이 아니어도 중첩 형식이 partial이 될 수 있음을 보여 줍니다.
class Container
{
partial class Nested
{
void Test() { }
}
partial class Nested
{
void Test2() { }
}
}
컴파일 타임에 부분 형식(Partial Type) 정의의 특성이 병합됩니다. 예를 들어, 다음 선언을 참조하십시오.
[SerializableAttribute]
partial class Moon { }
[ObsoleteAttribute]
partial class Moon { }
이러한 선언은 다음 선언과 같습니다.
[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }
다음은 모든 부분 형식(Partial Type) 정의에서 병합됩니다.
XML 주석
인터페이스
제네릭 형식 매개 변수 특성
클래스 특성
멤버
예를 들어, 다음 선언을 참조하십시오.
partial class Earth : Planet, IRotate { }
partial class Earth : IRevolve { }
이러한 선언은 다음 선언과 같습니다.
class Earth : Planet, IRotate, IRevolve { }
제한
partial 클래스 정의를 사용하여 작업할 때는 다음과 같은 몇 가지 규칙을 따라야 합니다.
동일한 형식의 일부를 의미하는 모든 부분 형식(Partial Type) 정의는 partial을 사용하여 한정해야 합니다. 예를 들어, 다음 클래스 선언에서는 오류가 발생합니다.
public partial class A { } //public class tcA { } // Error, must also be marked partial
partial 한정자는 class, struct 또는 interface 키워드 바로 앞에만 사용할 수 있습니다.
다음 예제와 같이 중첩된 부분 형식(Partial Type)은 부분 형식(Partial Type) 정의에 사용할 수 있습니다.
partial class ClassWithNestedClass { partial class NestedClass { } } partial class ClassWithNestedClass { partial class NestedClass { } }
동일한 형식의 일부를 의미하는 모든 부분 형식(Partial Type) 정의는 동일한 어셈블리와 동일한 모듈(.exe 또는 .dll 파일)에서 정의해야 합니다. partial 정의는 여러 모듈에 분산될 수 없습니다.
클래스 이름과 제네릭 형식 매개 변수는 모든 부분 형식(Partial Type) 정의에서 일치해야 합니다. 제네릭 형식은 부분 형식(Partial Type)이 될 수 있습니다. 각 partial 선언에서는 동일한 매개 변수 이름을 동일한 순서대로 사용해야 합니다.
부분 형식(Partial Type) 정의에 대한 다음 키워드는 선택적이지만 부분 형식(Partial Type) 정의 하나에 이러한 키워드가 있으면 동일한 형식의 다른 partial 정의에 지정된 키워드와 충돌하지 말아야 합니다.
예제 1
설명
다음 예제에서는 CoOrds 클래스의 필드와 생성자를 partial 클래스 정의 하나에서 선언하고 PrintCoOrds 멤버를 다른 partial 클래스 정의에서 선언합니다.
코드
public partial class CoOrds
{
private int x;
private int y;
public CoOrds(int x, int y)
{
this.x = x;
this.y = y;
}
}
public partial class CoOrds
{
public void PrintCoOrds()
{
Console.WriteLine("CoOrds: {0},{1}", x, y);
}
}
class TestCoOrds
{
static void Main()
{
CoOrds myCoOrds = new CoOrds(10, 15);
myCoOrds.PrintCoOrds();
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
// Output: CoOrds: 10,15
예제 2
설명
다음 예제에서는 partial 구조체와 인터페이스를 개발하는 방법을 보여 줍니다.
코드
partial interface ITest
{
void Interface_Test();
}
partial interface ITest
{
void Interface_Test2();
}
partial struct S1
{
void Struct_Test() { }
}
partial struct S1
{
void Struct_Test2() { }
}
부분 메서드(Partial Method)
partial 클래스 또는 구조체는 부분 메서드(Partial Method)를 포함할 수 있습니다. 클래스의 한 부분에는 메서드 시그니처가 포함됩니다. 같은 부분이나 다른 부분에 선택적 구현을 정의할 수 있습니다. 구현을 정의하지 않으면 컴파일할 때 메서드 및 메서드에 대한 모든 호출이 제거됩니다.
클래스의 한 부분을 구현하는 사용자는 부분 메서드를 사용하여 이벤트와 비슷한 메서드를 정의할 수 있습니다. 이 경우 클래스의 다른 부분을 구현하는 사용자는 해당 메서드를 구현할지 여부를 결정할 수 있습니다. 메서드를 구현하지 않을 경우, 컴파일러에서 메서드 시그니처와 메서드에 대한 모든 호출을 제거합니다. 호출의 인수 평가 시 발생할 수 있는 결과를 포함하여 메서드에 대한 호출은 런타임 시 영향이 없습니다. 따라서 partial 클래스의 코드에는 구현을 정의하지 않고도 부분 메서드를 마음대로 사용할 수 있습니다. 메서드를 호출만 하고 구현하지 않더라도 컴파일 타임 오류나 런타임 오류가 발생하지 않습니다.
부분 메서드는 생성된 코드를 사용자 지정할 때 특히 유용합니다. 부분 메서드를 사용하면 메서드 이름과 시그니처를 예약할 수 있습니다. 이렇게 하면 생성된 코드에서 메서드를 호출해도 메서드를 구현할지 여부를 개발자가 결정할 수 있습니다. partial 클래스와 마찬가지로 부분 메서드를 사용해도 별도의 런타임 비용 없이 코드 생성기에서 만든 코드와 개발자가 직접 만든 코드를 함께 사용할 수 있습니다.
부분 메서드 선언은 메서드 정의와 메서드 구현이라는 두 부분으로 구성됩니다. 이 두 부분은 partial 클래스에서 각각 별도의 부분에 포함되거나 동일한 부분에 포함될 수 있습니다. 구현을 선언하지 않으면 컴파일러에서 정의하는 선언 및 메서드에 대한 모든 호출을 최적화합니다.
// Definition in file1.cs
partial void onNameChanged();
// Implementation in file2.cs
partial void onNameChanged()
{
// method body
}
부분 메서드는 본문이 있는지 여부에 따라 정의 부분인지 구현 부분인지가 결정되기 때문에 extern이 될 수 없습니다.
부분 메서드는 제네릭 메서드일 수 있습니다. 제약 조건은 정의하는 부분 메서드 선언에 포함되며, 필요한 경우 구현하는 부분 메서드 선언에 반복될 수 있습니다. 매개 변수 및 형식 매개 변수 이름은 구현하는 선언과 정의하는 선언에서 동일하지 않아도 됩니다.
대리자를 정의 및 구현된 부분 메서드에 대해 만들 수 있지만 단지 정의된 부분 메서드에 대해서는 만들 수 없습니다.
C# 언어 사양
자세한 내용은 C# 언어 사양을 참조하십시오. 이 언어 사양은 C# 구문 및 사용법에 대한 신뢰할 수 있는 소스입니다.