web-dev-qa-db-ja.com

C#パーシャルクラスを使用するのが適切なのはいつですか?

なぜ私がそれらを使うのか、そしてそのプロセスでどのような利点があるのか​​、誰かが私に概要を教えてくれるかどうか疑問に思いました。

465
Asterix

部分クラスの最大の用途は、コード生成者/設計者の生活を楽にすることです。部分クラスを使用すると、ジェネレータは、生成する必要があるコードを単に生成することができ、ファイルに対するユーザの編集を処理する必要はありません。ユーザーは、2番目の部分クラスを持つことによって、新しいメンバーでクラスに自由に注釈を付けることができます。これは、懸念を切り離すための非常に明確な枠組みを提供します。

それを見るよりよい方法は、部分クラスの前にデザイナーがどのように機能したかを見ることです。 WinFormsデザイナは、コードを変更しないことについて強く憶測されたコメントを付けて、リージョン内のすべてのコードを吐き出します。後で処理するために生成されたコードを見つけるには、あらゆる種類のヒューリスティックを挿入する必要がありました。これで単にdesigner.csファイルを開くことができ、デザイナーに関連するコードのみが含まれているという高い信頼性が得られます。

384
JaredPar

別の用途は、異なるインターフェースの実装を分割することです。

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


partial class MyClass
{
    // implementation of IF1
}

partial class MyClass
{
    // implementation of IF2
}
236
relascope

他の答えはさておき...

私はそれらが神の階級をリファクタリングする際の足がかりとして役立つことがわかりました。あるクラスに複数の責任がある場合(特にそれが非常に大きいコードファイルである場合)、コードを体系化してからリファクタリングするための最初のパスとして、責任ごとに1x部分クラスを追加することが有益です。

実際には実行動作に影響を与えずにコードを読みやすくすることができるので、これは非常に役立ちます。また、責任をリファクタリングするのが簡単な場合や、他の側面と密接に関係している場合を特定するのにも役立ちます。

しかし、 - 明確にするために - これはまだ悪いコードです。開発の終わりには、クラスごとに1つの責任が必要です(NOTパーシャルクラスごと)。それは足がかりです:)

150
STW
  1. 複数開発者部分クラスを使用する複数の開発者は同じクラスで簡単に作業できます。
  2. コードジェネレータ部分クラスは主にコードジェネレータによって使用され、さまざまな問題を切り離します。
  3. 部分メソッド部分クラスを使用すると、開発者が単純にメソッドを定義でき、他の開発者がそれを実装できる場合にも、部分メソッドを定義できます。
  4. 部分的なメソッド宣言のみコードはメソッド宣言のみでコンパイルされ、メソッドの実装が存在しない場合は、そのコードは安全に削除されます。コンパイル時エラーは発生しません。

    ポイント4を確認するには、winformプロジェクトを作成し、Form1コンストラクタの後にこの行を含めて、コードをコンパイルしてみてください。

    partial void Ontest(string s);
    

部分クラスを実装する際に考慮すべき点がいくつかあります。 -

  1. 部分クラスの各部分で部分キーワードを使用します。
  2. 部分クラスの各部分の名前は同じである必要がありますが、部分クラスの各部分のソースファイル名は異なる場合があります。
  3. 部分クラスのすべての部分は同じ名前空間になければなりません。
  4. 部分クラスの各部分は、同じアセンブリまたはDLL内にある必要があります。つまり、異なるクラスライブラリプロジェクトのソースファイルに部分クラスを作成することはできません。
  5. 部分クラスの各部分は、同じアクセシビリティを持つ必要があります。 (プライベート、パブリック、または保護)
  6. 部分クラスのクラスまたはインタフェースを継承すると、その部分クラスのすべての部分によって継承されます。
  7. 部分クラスの一部が封印されている場合は、クラス全体が封印されます。
  8. 部分クラスの一部が抽象クラスの場合、クラス全体が抽象クラスと見なされます。
76
hellowahab

1つの大きな用途は、同じクラスに属する手書きコードから生成コードを分離することです。

たとえば、LINQ to SQLは部分クラスを使用するので、特定の機能の一部(多対多の関係など)を独自に実装して、コードを再生成してもそれらのカスタムコードは上書きされません。

WinFormsコードについても同じことが言えます。 Designerが生成したコードはすべて1つのファイルにまとめられているため、通常は触らないでください。手書きのコードは別のファイルに入っています。そうすることで、Designerで何かを変更しても、変更内容が失われることはありません。

55
Justin Niessner

Partial Classが自動コード生成に使用されていることは事実です。1つの用途は、何千行ものコードを持つかもしれない大きなクラスファイルを維持することです。あなたはあなたのクラスが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...
}

それが理にかなっていることを願っています!

19
kausar ahmed

巨大なクラスで作業しているとき、またはチームで作業しているときは、すべてをできるだけきれいにしておきます。オーバーライドせずに(または常に変更をコミットして)編集できます。

12
user406871

部分クラスは複数のファイルにまたがっています。

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

Partialを使用すると、クラスを物理的に複数のファイルに分割できます。

これは多くの場合コードジェネレータによって行われます。

通常のC#クラスでは、同じプロジェクト内の2つの別々のファイルでクラスを宣言することはできません。

しかし、部分的な修飾子を使えば、そうすることができます。

これは、一方のファイルが一般的に編集されており、もう一方のファイルが機械生成またはめったに編集されていない場合に便利です。

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キーワードを使用するか、クラス名の1つを変更します。

How does the C# compiler deal with partial classes?

上記のプログラムを逆アセンブルすると、ファイルA1.csとA2.csが削除されていることがわかります。

クラスAが存在することがわかります。

IL逆アセンブラSo:クラスAは、同じコードブロック内にメソッドA1とA2を含みます。 2つのクラスは1つにまとめられました。

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フォーム/ WPFプログラムを作成するときにVisual Studioで使用されます。

機械生成のC#コードは別のものです。

または、説明全体 をここで見つけることができます

11
Vivek Saurav

部分クラスの主な用途は生成コードです。 WPF(Windows Presentation Foundation)ネットワークを見ると、マークアップ(XML)を使用してUIを定義しています。そのマークアップは部分クラスにコンパイルされます。あなたはあなた自身の部分的なクラスでコードを記入します。

11
cletus

十分な大きさのクラスがあり、それが効果的なリファクタリングに向いていない場合は、それを複数のファイルに分割すると整理できます。

たとえば、ディスカッションフォーラムと製品システムを含むサイト用のデータベースがあり、2つの異なるプロバイダクラスを作成したくない場合(プロキシクラスと同じものではありません)、明確にすることができます。次のように、異なるファイルに単一の部分クラスを作成します。

MyProvider.cs - コアロジック

MyProvider.Forum.cs - 特にフォーラムに関連するメソッド

MyProvider.Product.cs - 商品のメソッド

物事を整理するための別の方法です。

また、他の人が言っているように、それは生成されたクラスにメソッドを追加する唯一の方法で、次回クラスが再生成されたときに追加が破棄される危険性はありません。これはテンプレート生成(T4)コード、ORMなどに役立ちます。

8
3Dave

サービス参照は、生成されたコードをユーザーが作成したコードから分離するのに部分クラスが役立つもう1つの例です。

サービス参照を更新するときにサービスクラスを上書きせずに「拡張」できます。

私が見たもう一つの用途は、

データアクセスロジックに関する大きな抽象クラスの拡張

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..
}

プリコンパイラ指令の代替として。

あなたがプリコンパイラ指令(すなわち#IF DEBUG)を使用するならば、あなたは実際のReleaseコードと混ざり合ったちょっと見栄えの良いコードになるでしょう。

このコードを含む別の部分クラスを作成し、部分クラス全体をディレクティブでラップするか、そのコードファイルをコンパイラに送信しないようにすることができます(事実上同じことを行います)。

6
STW

部分クラスを使用すると、単にソースファイルを追加するだけで、適切に設計されたプログラムに機能を追加することができます。たとえば、ファイルインポートプログラムは、それらを処理するモジュールを追加することによって、さまざまな種類の既知のファイルを追加できるように設計できます。たとえば、メインのファイルタイプコンバータに小さなクラスを含めることができます。

部分パブリッククラスzzFileConverterRegistrar 
イベントレジスタ(Byz mainConverterとしてのzzFileConverter)
 Sub registerAll(ByVal mainConverterとしてのzzFileConverter)
 RaiseEventレジスタ(mainConverter)
 End Sub 
 ]終了クラス

1つまたは複数の種類のファイルコンバータを登録したい各モジュールには、次のようなものが含まれます。

部分パブリッククラスzzFileConverterRegistrar 
プライベートSub RegisterGif(ByVal mainConverter as zzFileConverter)Me.Register 
 mainConverter.RegisterConverter( "GIF"、GifConverter.NewFactory))
 End Sub 
エンドクラス

メインのファイルコンバータクラスは「公開」されていないことに注意してください。アドインモジュールがフックできる小さなスタブクラスを公開しているだけです。名前の競合が発生する可能性がわずかにありますが、各アドインモジュールの「登録」ルーチンが、取り扱うファイルの種類に従って名前が付けられている場合は、おそらく問題にならないはずです。そのようなことが心配な場合は、登録サブルーチンの名前にGUIDを付けることができます。

編集/補遺 明確にするために、これの目的は、さまざまな別々のクラスがメインプログラムまたはクラスにそれらについて知らせることができる手段を提供することです。メインファイルコンバータがzzFileConverterRegistrarに対して行う唯一のことは、そのインスタンスを1つ作成し、Registerイベントを発生させるregisterAllメソッドを呼び出すことです。そのイベントをフックしたいモジュールはそれに応答して任意のコードを実行できます(それは全体的な考えです)が、zzFileConverterRegistrarクラスを不適切に拡張することによってモジュールができることは他にはありません。 。不適切に書かれたエクステンションが別の不適切に書かれたエクステンションを壊すことは確かに可能ですが、それに対する解決策は彼のエクステンションを壊されたくない人には単にそれを正しく書かせることです。

部分クラスを使用せずに、メインファイルコンバータクラス内のどこかにコードを少し含めることもできます。

 RegisterConverter( "GIF"、GifConvertor.NewFactory)[.____。RegisterConverter( "BMP"、BmpConvertor.NewFactory)[.____。RegisterConverter( "JPEG"、JpegConvertor.NewFactory)

しかし、別のコンバータモジュールを追加するには、コンバータコードのその部分に入り、新しいコンバータをリストに追加する必要があります。部分的なメソッドを使用することで、これは必要なくなりました - すべてのコンバータは自動的にインクルードされます。

4
supercat

ほとんどの人は、partialは、生成されたコードファイルを持つクラスやインタフェースに対してのみ使うべきだと述べています。私は同意しません、そしてここにその理由があります。

一例として、C#System.Mathクラスを見てみましょう。それはクラスです。私は70以上のメソッドをすべて同じ単一のコードファイルに詰め込もうとはしませんでした。維持するのは悪夢だろう。

各数学メソッドを個々の部分クラスファイルに、すべてのコードファイルをプロジェクト内のMathフォルダーに配置すると、組織が大幅に整理されます。

同じことが、大量の多様な機能を持つ他の多くのクラスにも当てはまります。たとえば、PrivateProfile APIを管理するためのクラスは、単一のプロジェクトフォルダー内のクリーンな一連の部分クラスファイルに分割されることでメリットが得られます。

個人的には、私はまたほとんどの人が "ヘルパー"または "ユーティリティ"クラスと呼ぶものを各メソッドまたはメソッド機能グループの個々の部分ファイルに分割します。たとえば、あるプロジェクトでは、文字列ヘルパークラスには約50のメソッドがあります。リージョンを使用しても、それは長くて扱いにくいコードファイルになるでしょう。各メソッドに個別の部分クラスファイルを使用して保守するのはかなり簡単です。

これを行う際には、部分クラスの使用には慎重に注意し、プロジェクト全体を通してすべてのコードファイルのレイアウトを統一してください。クラスパブリック列挙体およびクラスプライベートメンバを、それらが含まれる部分ファイルだけに固有のものでない限り、ファイル全体に広げるのではなく、フォルダ内のCommon.csまたは同様の名前のファイルに配置するなど.

クラスを別々のファイルに分割すると、現在のファイルの2つの異なるセクションを同時に表示できるテキストエディタの分割バーを使用することもできなくなります。

3
deegee

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 { }
}
3
Eli

部分クラスは最近、新しいメソッドがファイルの同じ部分に追加された1つのファイルに複数の開発者が追加するソース管理に役立ちました(Resharperによって自動化されています)。

これらのgitへのプッシュはマージの衝突を引き起こしました。マージツールに新しいメソッドを完全なコードブロックとして使用するように指示する方法はありませんでした。

この点で部分クラスは開発者が彼らのファイルのバージョンに固執することを可能にします、そして、我々は後で手でそれらをマージすることができます。

例 -

  • MainClass.cs - フィールド、コンストラクタなどを保持します
  • MainClass1.cs - 開発者が実装した新しいコード
  • MainClass2.cs - 彼らの新しいコードのためのもう一つの開発者クラスです。
3
Jay

これが部分クラスの利点のいくつかのリストです。

読みやすく理解しやすいように、UI設計コードとビジネスロジックコードを分離することができます。たとえば、Visual Studioを使用してWebアプリケーションを開発し、新しいWebフォームを追加すると、 "aspx.cs"と "aspx.designer.cs"という2つのソースファイルがあります。これら2つのファイルは、partialキーワードを持つ同じクラスを持ちます。 "。aspx.cs"クラスはビジネスロジックコードを持ち、 "aspx.designer.cs"はユーザーインターフェイスコントロール定義を持ちます。

自動生成されたソースを扱うときは、ソースファイルを再作成しなくてもコードをクラスに追加できます。たとえば、LINQ to SQLを使用してDBMLファイルを作成しているとします。テーブルをドラッグアンドドロップすると、designer.csに部分クラスが作成され、すべてのテーブル列にそのクラスのプロパティが設定されます。 UIグリッドにバインドするには、このテーブルにさらに列が必要ですが、データベーステーブルに新しい列を追加したくないため、この列に新しいプロパティを持つ別のソースファイルを作成することができます。部分クラスになります。そのため、データベーステーブルとDBMLエンティティの間のマッピングに影響しますが、追加のフィールドを簡単に取得できます。それはあなたがシステム生成コードを台無しにすることなくあなた自身でコードを書くことができることを意味します。

複数の開発者が同時にそのクラスのコードを書くことができます。

大規模なクラスを圧縮することで、アプリケーションをより良く維持することができます。インターフェイスの実装に応じて複数のソースファイルを作成できるように、複数のインターフェイスを持つクラスがあるとします。ソースファイルが部分的なクラスを持つように実装されたインターフェースを理解し維持するのは簡単です。

1
shashi

私はこの質問が本当に古いことを知っていますが、私は部分クラスの私の見方を加えたいと思います。

私が個人的に部分クラスを使用する理由の1つは、プログラム、特にステートマシン用のバインディングを作成するときです。

たとえば、OpenGLはステートマシンです。グローバルに変更できるメソッドのヒープがあります。 10k LOCを簡単に超えることができます。

部分クラスは私にとってはこれを打破するでしょうそしては私が素早くメソッドを見つけるのを助けます。

1
user6630825

かなりの大きさや複雑さを持つ入れ子クラスを含むクラスがあるときはいつでも、そのクラスをpartialとしてマークし、入れ子クラスを別のファイルに入れます。 [クラス名]。[ネストクラス名] .csという規則を使用して、ネストクラスを含むファイルに名前を付けます。

次のMSDNブログでは、保守容易性のための部分クラスと入れ子クラスの使用について説明しています。 http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes入れ子になったクラスの保守容易性.aspx

1

部分クラスは主にコード生成を支援するために導入されているので、私たち(ユーザー)が生成するたびにASP.NETの.designer.csクラスのような生成されたクラスに対するすべての作業や変更を失うことはありません。コードLINQ、EntityFrameworks、ASP.Net生成コードに部分クラスを使用するので、部分クラスとメソッドを利用してこれらの生成コードのロジックを安全に追加または変更できますが、部分クラスを使用して生成コードに追加する前に十分注意してくださいビルドを中断した方が簡単ですが、ランタイムエラーが発生した場合は最悪です。詳細については、これをチェックしてください http://www.4guysfromrolla.com/articles/071509-1.aspx

0
Kiran Bheemarti