[C#] C # 부분 클래스를 사용하는 것이 적절한 경우는 언제입니까?


Answers

부분 클래스의 가장 큰 용도는 코드 생성기 / 디자이너의 삶을 편하게 만드는 것입니다. 부분 클래스를 사용하면 생성자는 생략해야하는 코드를 간단하게 생략 할 수 있으며 파일에 대한 사용자 편집을 처리 할 필요가 없습니다. 사용자는 마찬가지로 두 번째 부분 클래스를 사용하여 클래스에 새 멤버를 자유롭게 주석으로 지정할 수 있습니다. 이것은 관심사 분리를위한 매우 깨끗한 틀을 제공합니다.

좀 더 나은 방법은 디자이너가 부분 클래스보다 먼저 어떻게 작동하는지 확인하는 것입니다. WinForms 디자이너는 코드를 수정하지 않는 것에 대해 강하게 말한 의견으로 지역 안의 모든 코드를 뱉어 낼 것입니다. 나중에 처리하기 위해 생성 된 코드를 찾기 위해 모든 종류의 발견 적 방법을 삽입해야했습니다. 이제는 단순히 designer.cs 파일을 열고 디자이너와 관련된 코드 만 포함하고 있다는 확신을 가질 수 있습니다.

Question

누군가 내가 왜 내가 그들을 사용할 것인지와 내가 그 과정에서 얻게 될 이점에 대한 개요를 줄 수 있는지 궁금해하고 있었다.




부분 클래스를 사용하면 소스 파일을 추가하기 만하면 적절하게 설계된 프로그램에 기능을 추가 할 수 있습니다. 예를 들어 파일 가져 오기 프로그램은 파일을 처리하는 모듈을 추가하여 다른 유형의 알려진 파일을 추가 할 수 있도록 설계 될 수 있습니다. 예를 들어 주 파일 형식 변환기에 작은 클래스가 포함될 수 있습니다.

Partial Public Class zzFileConverterRegistrar
    Event Register(ByVal mainConverter as zzFileConverter)
    Sub registerAll(ByVal mainConverter as zzFileConverter)
        RaiseEvent Register(mainConverter)
    End Sub
End Class

하나 이상의 파일 변환기 유형을 등록하려는 각 모듈에는 다음과 같은 내용이 포함될 수 있습니다.

Partial Public Class zzFileConverterRegistrar
    Private Sub RegisterGif(ByVal mainConverter as zzFileConverter) Handles Me.Register
        mainConverter.RegisterConverter("GIF", GifConverter.NewFactory))
    End Sub
End Class

주 파일 변환기 클래스는 "노출 된"것이 아니라 단지 추가 모듈이 연결할 수있는 약간의 스텁 클래스를 노출합니다. 충돌에 이름을 붙일 수있는 약간의 위험이 있습니다. 그러나 각 애드 인 모듈의 "register"루틴이 다루는 파일 유형에 따라 이름이 지정되면 문제가 발생하지 않을 것입니다. 등록 서블 루틴의 이름에 GUID를 붙이면 걱정할 수 있습니다.

Edit / Addendum 명확하게하기 위해, 이것의 목적은 다양한 분리 된 클래스들이 주 프로그램이나 클래스가 그것들에 대해 알 수있게하는 수단을 제공하는 것이다. 주 파일 변환기가 zzFileConverterRegistrar로 수행 할 수있는 유일한 작업은 하나의 인스턴스를 작성하고 registerAll 메소드를 호출하여 Register 이벤트를 발생시키는 것입니다. 해당 이벤트를 후크하려는 모듈은 이에 대한 응답으로 임의의 코드를 실행할 수 있습니다 (전체 아이디어입니다). zzFileConverterRegistrar 클래스를 부적절하게 확장하여 모듈이 수행 할 수있는 일은 아무것도 없습니다. 이름이 다른 것의 이름과 일치하는 메소드를 정의하는 것 외에는 . 하나의 부적절하게 작성된 확장이 다른 부적절하게 작성된 확장을 깨뜨리는 것은 가능할 수 있지만, 그 해결책은 확장을 깨뜨리지 않고 단순히 올바르게 작성하는 것을 원하지 않는 사람들을위한 것입니다.

부분 클래스를 사용하지 않고도 주 파일 변환기 클래스의 어딘가에 약간의 코드가있을 수 있습니다.

  RegisterConverter("GIF", GifConvertor.NewFactory)
  RegisterConverter("BMP", BmpConvertor.NewFactory)
  RegisterConverter("JPEG", JpegConvertor.NewFactory)

다른 변환기 모듈을 추가하려면 변환기 코드의 해당 부분으로 가서 새 변환기를 목록에 추가해야합니다. 더 이상 필요하지 않은 부분 방법을 사용하면 모든 변환기가 자동으로 포함됩니다.




중요한 크기 / 복잡성을 갖는 중첩 클래스를 포함하는 클래스가있을 때마다 클래스를 partial 클래스로 표시하고 중첩 클래스를 별도의 파일에 저장합니다. [class name]. [nested class name] .cs 규칙을 사용하여 중첩 클래스를 포함하는 파일의 이름을 지정합니다.

다음 MSDN 블로그는 유지 관리를 위해 부분 클래스를 중첩 클래스와 함께 사용하는 방법을 설명합니다. http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for-maintainability.aspx




Partial Class가 자동 코드 생성에 사용되는 것은 사실이지만, 한 가지 용도는 수천 줄의 코드를 가진 대형 클래스 파일을 유지 관리하는 것입니다. 당신은 당신의 수업이 1 만 라인으로 끝날지 모르고 다른 이름으로 새로운 수업을 만들고 싶지 않습니다.

public partial class Product
{
    // 50 business logic embedded in methods and properties..
}

public partial class Product
{
    // another 50 business logic embedded in methods and properties..
}
//finally compile with product.class file.

또 다른 가능한 사용은 둘 이상의 개발자가 서로 다른 장소에 저장되는 동일한 클래스에서 작업 할 수 있다는 것입니다. 사람들은 웃을 지 모르지만 때로는 소수 일 수 있다는 것을 결코 알지 못합니다.

Product1.cs

public partial class Product
{
    //you are writing the business logic for fast moving product
}

Product2.cs

public partial class Product
{
    // Another developer writing some business logic...
}

그것이 의미가 있기를 바랍니다!




또 다른 용도는 다른 인터페이스의 구현을 분리하는 것입니다. 예 :

partial class MyClass : IF1, IF2, IF3
{
    // main implementation of MyClass
}


partial class MyClass
{
    // implementation of IF1
}

partial class MyClass
{
    // implementation of IF2
}



서비스 참조는 부분 클래스가 생성 된 코드를 사용자 작성 코드와 분리하는 데 유용한 또 다른 예제입니다.

서비스 참조를 업데이트 할 때 덮어 쓰지 않고도 서비스 클래스를 "확장"할 수 있습니다.




내가 본 또 다른 용도는,

데이터 액세스 로직과 관련하여 큰 추상 클래스를 확장하면,

나는 Post.cs, Comment.cs, Pages.cs라는 이름의 다양한 파일을 가지고있다.

in Post.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of post..
}


in Comment.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of comment..
}

in Pages.cs 

public partial class XMLDAO :BigAbstractClass
{
// CRUD methods of Pages..
}



부분 클래스는 주로 코드 생성자를 돕기 위해 도입되었으므로 우리는 생성 할 때마다 ASP.NET의 .designer.cs 클래스와 같은 생성 된 클래스에 대한 모든 작업 / 변경 사항을 잃지 않으므로 생성하는 거의 모든 새로운 도구 코드 LINQ, EntityFrameworks, ASP.NET은 생성 된 코드에 부분 클래스를 사용하므로 Partial 클래스 및 메서드를 활용하여 생성 된 코드의 논리를 안전하게 추가하거나 변경할 수 있지만 Partial 클래스를 사용하여 생성 된 코드에 내용을 추가하기 전에 매우주의 깊게 작성해야합니다. 우리가 빌드를 깨면 쉬울 것이지만 런타임 오류를 도입하면 최악입니다. 자세한 내용은 http://www.4guysfromrolla.com/articles/071509-1.aspx 확인하십시오 http://www.4guysfromrolla.com/articles/071509-1.aspx




효과적인 리펙토링에 적합하지 않은 충분히 큰 클래스를 여러 파일로 분리하면 클래스를 정리하는 데 도움이됩니다.

예를 들어, 토론 포럼과 제품 시스템이 포함 된 사이트에 대한 데이터베이스가 있고 두 개의 다른 공급자 클래스를 만들지 않으려면 (분명히 프록시 클래스와 동일한 것은 아닙니다), 다음과 같이 할 수 있습니다. 같은 다른 파일에 하나의 부분 클래스 만들기

MyProvider.cs - 핵심 논리

MyProvider.Forum.cs - 포럼과 관련된 메소드

MyProvider.Product.cs - 제품에 대한 메소드

모든 것을 정리하는 또 다른 방법 일뿐입니다.

또한 다른 사람들이 말했듯이, 다음 번에 클래스를 다시 생성 할 때 클래스가 추가되는 위험을 감수하지 않고 생성 된 클래스에 메서드를 추가하는 유일한 방법입니다. 이것은 템플리트 생성 (T4) 코드, ORM 등에 유용합니다.




다음은 부분 클래스의 몇 가지 장점 목록입니다.

UI 디자인 코드와 비즈니스 로직 코드를 분리하여 읽고 이해하기 쉽도록 할 수 있습니다. 예를 들어 Visual Studio를 사용하여 웹 응용 프로그램을 개발하고 새로운 웹 폼을 추가하면 "aspx.cs"및 "aspx.designer.cs"라는 두 개의 소스 파일이 있습니다. 이 두 파일은 부분 키워드와 동일한 클래스입니다. "aspx.designer.cs"에는 사용자 인터페이스 컨트롤 정의가있는 반면 ".aspx.cs"클래스에는 비즈니스 로직 코드가 있습니다.

자동으로 생성 된 소스로 작업 할 때 소스 파일을 다시 만들 필요없이 코드를 클래스에 추가 할 수 있습니다. 예를 들어 LINQ to SQL을 사용하여 작업하고 DBML 파일을 만듭니다. 이제 테이블을 드래그 앤 드롭하면 designer.cs에 부분 클래스가 생성되고 모든 테이블 열은 클래스에 속성이 있습니다. 이 표에서 UI 표에 바인딩 할 열이 더 있어야하지만 새 열을 데이터베이스 표에 추가하지 않으므로 해당 열의 새 속성을 가진이 클래스에 대한 별도의 소스 파일을 만들 수 있습니다. 부분 수업. 따라서 데이터베이스 테이블과 DBML 엔티티 간의 매핑에 영향을 미치지 만 추가 필드를 쉽게 얻을 수 있습니다. 즉, 시스템에서 생성 된 코드를 엉망으로 만들지 않고 코드를 직접 작성할 수 있습니다.

둘 이상의 개발자가 동시에 클래스의 코드를 작성할 수 있습니다.

대형 클래스를 압축하여 응용 프로그램을보다 잘 유지 관리 할 수 ​​있습니다. 인터페이스 구현에 따라 여러 소스 파일을 만들 수 있도록 여러 인터페이스가있는 클래스가 있다고 가정합니다. 소스 파일에 부분 클래스가 구현 된 인터페이스를 쉽게 이해하고 유지 관리 할 수 ​​있습니다.




부분 클래스의 주요 용도는 생성 된 코드입니다. WPF (Windows Presentation Foundation) 네트워크를 보면 마크 업 (XML)을 사용하여 UI를 정의 할 수 있습니다. 이 마크 업은 부분 클래스로 컴파일됩니다. 당신은 자신의 부분 수업으로 코드를 작성합니다.




한 가지 유용한 점은 생성 된 코드를 같은 클래스에 속한 손으로 작성된 코드와 분리하는 것입니다.

예를 들어 LINQ to SQL이 부분 클래스를 사용하기 때문에 특정 기능 (예 : 다 대다 관계) 구현을 직접 작성할 수 있으며 코드를 다시 생성 할 때 이러한 사용자 지정 코드 조각을 덮어 쓰지 않습니다.

WinForms 코드도 마찬가지입니다. 디자이너가 생성 한 모든 코드는 일반적으로 만지지 않는 한 파일에 저장됩니다. 직접 작성한 코드는 다른 파일에 저장됩니다. 그렇게하면 Designer에서 어떤 것을 변경하면 변경 사항이 날아 가지 않습니다.




거대한 클래스로 작업 할 때 모든 것을 가능한 한 깨끗하게 유지하거나 팀에서 작업 할 때 재정의 (또는 항상 커밋 변경)없이 편집 할 수 있습니다.




MSDN :

1. 컴파일 시간에 부분 유형 정의의 속성이 병합됩니다. 예를 들어, 다음 선언을 고려하십시오.

[SerializableAttribute]
partial class Moon { }

[ObsoleteAttribute]
partial class Moon { }

그것들은 다음과 같은 선언들과 같습니다 :

[SerializableAttribute]
[ObsoleteAttribute]
class Moon { }

다음은 모든 부분 유형 정의에서 병합됩니다.

  • XML 주석

  • 인터페이스

  • 제네릭 형식 매개 변수 특성

  • 클래스 속성

  • 회원

2. 중첩 된 부분 클래스도 부분 클래스가 될 수 있습니다.

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}

partial class ClassWithNestedClass
{
    partial class NestedClass { }
}



대부분의 사람들은 partial 은 생성 된 코드 파일이 있거나 인터페이스 용 클래스에만 사용해야한다고 말합니다. 나는 동의하지 않으며, 여기에 이유가있다.

한 가지 예를 들어 보겠습니다. C # System.Math 클래스 ... 클래스 입니다. 70 개 이상의 메소드를 모두 동일한 단일 코드 파일로 채우려하지 않았습니다. 유지하는 것은 악몽 일 것입니다.

각 수학 방법을 개별 부분 클래스 파일에 배치하고 모든 코드 파일을 프로젝트의 수학 폴더에 배치하면 조직이 훨씬 깔끔 해집니다.

많은 기능을 가진 다른 많은 클래스에서도 마찬가지입니다. 예를 들어, PrivateProfile API를 관리하는 클래스는 단일 프로젝트 폴더에서 부분 클래스 파일의 깨끗한 세트로 분리되어 유용 할 수 있습니다.

개인적으로 필자는 또한 대부분의 사람들이 "helper"또는 "utility"클래스라고 부르는 것을 각 메소드 나 메소드 기능 그룹의 개별 부분 파일로 분리했습니다. 예를 들어 한 프로젝트에서 문자열 도우미 클래스는 거의 50 가지 방법을 사용합니다. 이는 지역을 사용하는 경우에도 다루기 힘든 코드 파일입니다. 각 메서드에 대해 개별 부분 클래스 파일을 사용하여 유지 관리하는 것이 훨씬 쉽습니다.

부분 클래스를 사용하는 경우주의를 기울여야하고 모든 코드 파일 레이아웃을 프로젝트 전체에서 일관되게 유지해야합니다. 클래스 공개 열거 형 및 클래스 전용 멤버를 폴더에있는 Common.cs 또는 비슷한 이름의 파일에 배치하는 것 (예 : 포함 된 부분 파일에만 해당되는 경우가 아닌 경우)

클래스를 별도의 파일로 분리하면 현재 파일의 두 섹션을 동시에 볼 수있는 텍스트 편집기 분할 막대를 사용할 수 없게됩니다.




나는이 질문이 정말로 오래되었다는 것을 알고있다. 그러나 나는 부분 수업에 자신의 생각을 더하고 싶다.

개인적으로 부분 클래스를 사용하는 한 가지 이유는 프로그램, 특히 상태 시스템에 대한 바인딩을 만들 때입니다.

예를 들어, OpenGL은 상태 머신이며, 전역 적으로 변경 될 수있는 메소드의 이 있습니다. 그러나 많은 경험이있는 OpenGL과 유사한 바인딩을 사용하면 클래스가 쉽게 10k LOC를 초과 할 수 있습니다.

부분 수업은 나를 위해 이것을 깨고 방법을 빨리 찾을 수 있도록 도와 줄 것입니다.




다른 답변을 제외하고 ...

나는 리팩토링의 신 클래스에 스테핑 스톤으로 도움이되는 것을 발견했다. 클래스가 여러 책임 (특히 코드 파일이 매우 큰 경우)이 있다면 코드를 구성하고 리팩토링하는 첫 번째 단계로 책임 당 1x 부분 클래스를 추가하는 것이 좋습니다.

이는 실제로 실행 동작에 영향을 미치지 않으면 서 코드를 훨씬 쉽게 읽을 수 있도록 도와주기 때문에 크게 도움이됩니다. 또한 책임을 리팩토링하기가 쉬운시기를 식별하거나 다른 측면과 밀접하게 관련되어 있는지 확인할 수 있습니다.

그러나 명확한 - 아직 나쁜 코드입니다. 개발이 끝나면 부분 클래스 당 하나의 책임을 요구합니다. 그것은 단지 발판입니다 :)




부분 클래스는 최근에 여러 개발자가 한 파일에 새 메서드가 추가 된 (Resharper에서 자동화 된) 파일의 동일한 부분에 추가하는 소스 제어를 도왔습니다.

git에 푸시하면 병합 충돌이 발생합니다. 새 코드를 완전한 코드 블록으로 사용하도록 병합 도구에 지시 할 방법이 없습니다.

이런면에서 부분 클래스는 개발자가 파일 버전을 고수 할 수있게 해주 며 나중에 손으로 다시 병합 할 수 있습니다.

예 -

  • MainClass.cs - 필드, 생성자 등을 보유합니다.
  • MainClass1.cs - 개발자가 구현할 때 새로운 코드
  • MainClass2.cs - 새로운 코드에 대한 또 다른 개발자 클래스입니다.



부분 클래스는 여러 파일에 걸쳐 있습니다.

How can you use the partial modifier on a C# class declaration?

partial을 사용하면 클래스를 물리적으로 여러 파일로 분리 할 수 ​​있습니다.

이것은 종종 코드 생성기에 의해 수행됩니다.

일반 C # 클래스를 사용하면 같은 프로젝트에있는 두 개의 개별 파일로 클래스를 선언 할 수 없습니다.

그러나 부분 수정자를 사용하여 할 수 있습니다.

한 파일을 일반적으로 편집하고 다른 파일을 컴퓨터에서 생성하거나 거의 편집하지 않는 경우에 유용합니다.

An Example will clear your concept.

class Program
{
    static void Main()
    {
    A.A1();
    A.A2();
    }
}

//Contents of file A1.cs: C#

using System;

partial class A
{
    public static void A1()
    {
    Console.WriteLine("A1");
    }
}

//Contents of file A2.cs: C#

using System;

partial class A
{
    public static void A2()
    {
    Console.WriteLine("A2");
    }
}

Output

A1
A2

부분은 여기에 필요합니다.

If you remove the partial modifier, you will get an error containing this text: [The namespace '<global namespace>' already contains a definition for 'A'].

팁 : 이 문제를 해결하려면 partial 키워드를 사용하거나 클래스 이름 중 하나를 변경할 수 있습니다.

How does the C# compiler deal with partial classes?

위의 프로그램을 해체하면 A1.cs 및 A2.cs 파일이 제거됩니다.

클래스 A가 존재한다는 것을 알 수 있습니다.

IL 디스어셈블러 그래서 : 클래스 A는 동일한 코드 블록에 A1과 A2 메소드를 포함 할 것입니다. 두 클래스는 하나에 병합되었습니다.

A1.cs와 A2.cs의 컴파일 결과 : C #

internal class A
{
    // Methods
    public static void A1()
    {
    Console.WriteLine("A1");
    }

    public static void A2()
    {
    Console.WriteLine("A2");
    }
}

개요

부분 클래스는 특정 C # 프로그래밍 상황을 단순화 할 수 있습니다.

Windows Forms / WPF 프로그램을 만들 때 Visual Studio에서 자주 사용됩니다.

컴퓨터에서 생성 된 C # 코드는 별도입니다.

또는 전체 설명을 here 찾을 수 here .




사전 컴파일러 지시문의 대체 방법.

사전 컴파일러 지시어 (즉, #IF DEBUG )를 사용하면 실제 릴리스 코드와 혼합 된 거칠게 보이는 코드로 끝납니다.

이 코드를 포함하기 위해 별도의 부분 클래스를 생성하고 지시문에 전체 부분 클래스를 래핑하거나 해당 코드 파일을 생략하여 컴파일러로 보내지 않도록 할 수 있습니다.




  1. 부분 클래스를 사용하는 여러 개발자 여러 개발자 가 같은 클래스에서 쉽게 작업 할 수 있습니다.
  2. 코드 생성기 (Code Generator) 부분적인 클래스는 코드 생성기에서 주로 사용되어 서로 다른 관심사를 구분합니다.
  3. 부분 메소드 Partial 클래스를 사용하여 개발자가 메소드를 간단하게 정의 할 수있는 곳에서 Partial 메소드를 정의 할 수도 있고 다른 개발자가이를 구현할 수도 있습니다.
  4. Partial Method Declaration only 코드는 메소드 선언으로 만 컴파일되며, 메소드의 구현이 존재하지 않으면 컴파일러는 해당 코드를 안전하게 제거 할 수 있으며 컴파일 타임 오류가 발생하지 않습니다.

    4. winform 프로젝트를 만들고 Form1 생성자 다음에이 행을 포함시키고 코드 컴파일을 시도하십시오.

    partial void Ontest(string s);
    

다음은 부분 클래스를 구현하는 동안 고려해야 할 몇 가지 사항입니다.

  1. 부분 클래스의 각 부분에 부분 키워드를 사용하십시오.
  2. 부분 클래스의 각 부분의 이름은 동일해야하지만 부분 클래스의 각 부분에 대한 소스 파일 이름은 다를 수 있습니다.
  3. 부분 클래스의 모든 부분은 동일한 네임 스페이스에 있어야합니다.
  4. 부분 클래스의 각 부분은 동일한 어셈블리 또는 DLL에 있어야합니다. 즉, 다른 클래스 라이브러리 프로젝트의 소스 파일에 부분 클래스를 만들 수 없습니다.
  5. 부분 클래스의 각 부분은 동일한 액세스 가능성을 가져야합니다. (예 : 개인, 공개 또는 보호 된)
  6. 부분 클래스에서 클래스 또는 인터페이스를 상속하는 경우 해당 부분 클래스의 모든 부분에서 상속됩니다.
  7. 부분 클래스의 일부가 봉인 된 경우 전체 클래스가 봉인됩니다.
  8. 부분 클래스의 일부가 abstract 인 경우, 전체 클래스는 추상 클래스로 간주됩니다.