回答:
部分クラスの最大の用途は、コードジェネレーター/デザイナーの作業を容易にすることです。部分クラスを使用すると、ジェネレーターは、必要なコードを簡単に出力でき、ユーザーによるファイルの編集を処理する必要がありません。同様に、ユーザーは2番目の部分クラスを使用して、クラスに新しいメンバーで注釈を付けることができます。これにより、問題を分離するための非常にクリーンなフレームワークが提供されます。
それを見るより良い方法は、部分クラスの前にデザイナーがどのように機能したかを確認することです。WinFormsデザイナは、コードを変更しないことについて強くコメントされたコメントで、領域内のすべてのコードを吐き出します。後で処理するために生成されたコードを見つけるには、あらゆる種類のヒューリスティックを挿入する必要がありました。これで、designer.csファイルを開くだけで、デザイナーに関連するコードのみが含まれていると確信できます。
別の用途は、異なるインターフェースの実装を分割することです。例:
partial class MyClass : IF1, IF2, IF3
{
// main implementation of MyClass
}
partial class MyClass
{
// implementation of IF1
}
partial class MyClass
{
// implementation of IF2
}
Implements
キーワードを使用してメソッドがインターフェイスに属していることを示すため)
他の答えは別として...
神のクラスをリファクタリングする際の足がかりとして役立つことがわかりました。クラスに複数の責任がある場合(特に、コードファイルが非常に大きい場合)、コードを整理してリファクタリングするための最初のパスとして、責任ごとに1xの部分クラスを追加すると効果的です。
これは、実行動作に実際に影響を与えずにコードを読みやすくするのに役立つため、非常に役立ちます。また、責任が簡単にリファクタリングされたり、他の側面と密接に絡み合ったりする時期を特定するのにも役立ちます。
しかし-明確にする-これは開発の終了時に、あなたはまだ、クラスごとの(1人の責任たい、まだ悪いコードではありませんパーシャルクラスごとに)。それは単なる踏み石です:)
部分的なメソッド宣言のみコードはメソッド宣言のみでコンパイルされ、メソッドの実装が存在しない場合、コンパイラーはそのコードを安全に削除でき、コンパイル時エラーは発生しません。
ポイント4を検証するには、Winformプロジェクトを作成し、Form1コンストラクターの後にこの行を含めて、コードをコンパイルしてみます。
partial void Ontest(string s);
部分クラスを実装する際に考慮すべきいくつかのポイントを次に示します。
1つの優れた使用法は、同じクラスに属する手書きのコードから生成されたコードを分離することです。
たとえば、LINQ to SQLは部分クラスを使用するため、特定の機能(多対多の関係など)の独自の実装を記述でき、それらのカスタムコードは、コードを再生成しても上書きされません。
WinFormsコードについても同様です。Designerで生成されたコードはすべて、通常は変更しない1つのファイルに入っています。手書きのコードは別のファイルに入ります。そうすれば、Designerで何かを変更しても、その変更が吹き飛ばされることはありません。
パーシャルクラスが自動コード生成で使用されることは事実です。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.
別の考えられる用途は、複数の開発者が異なる場所に格納されているため、同じクラスで作業できることです。人々は笑うかもしれませんが、それが時々一握りであることができることをあなたは決して知りません。
public partial class Product
{
//you are writing the business logic for fast moving product
}
public partial class Product
{
// Another developer writing some business logic...
}
それが理にかなっていることを願っています!
部分クラスは複数のファイルにまたがっています。
C#クラス宣言で部分修飾子をどのように使用できますか?
部分クラスを使用すると、クラスを物理的に複数のファイルに分離できます。これは多くの場合、コードジェネレーターによって行われます。
例
通常のC#クラスでは、同じプロジェクトの2つの別々のファイルでクラスを宣言することはできません。しかし、partial
修飾子を使用すると、できます。
これは、一方のファイルが一般的に編集され、もう一方のファイルが機械で生成されるか、ほとんど編集されない場合に役立ちます。
明確にするための例を次に示します。
class Program
{
static void Main()
{
A.A1();
A.A2();
}
}
ファイルA1.csの内容:C#
using System;
partial class A
{
public static void A1()
{
Console.WriteLine("A1");
}
}
ファイルA2.csの内容:C#
using System;
partial class A
{
public static void A2()
{
Console.WriteLine("A2");
}
}
出力:
A1
A2
ここでは部分的に入力する必要があります。
partial
修飾子を削除すると、次のテキストを含むエラーが発生します。
[名前空間 '
<global namespace>
'には既に' 'の定義が含まれていますA
]。
ヒント:
これを修正するには、partial
キーワードを使用するか、クラス名の1つを変更します。
C#コンパイラは部分クラスをどのように扱いますか?
上記のプログラムを逆アセンブルすると(IL Disassemblerを使用)、ファイルA1.csおよびA2.csが削除されていることがわかります。クラスAが存在することがわかります。
クラス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");
}
}
概要
巨大なクラスで作業しているとき、またはチームで作業しているときは、すべてをできるだけクリーンに保ち、オーバーライドせずに(または常に変更をコミットして)編集できます。
効果的なリファクタリングに適さない十分に大きなクラスがある場合は、クラスを複数のファイルに分割すると、整理された状態を維持できます。
たとえば、ディスカッションフォーラムと製品システムを含むサイトのデータベースがあり、2つの異なるプロバイダークラスを作成したくない場合(明確にするために、プロキシクラスと同じものではありません)、次のことができます。次のような異なるファイルに単一の部分クラスを作成します
MyProvider.cs-コアロジック
MyProvider.Forum.cs-フォーラム専用のメソッド
MyProvider.Product.cs-製品のメソッド
これは、物事を整理しておくためのもう1つの方法です。
また、他の人が言ったように、クラスが次に再生成されるときに追加が破棄されるリスクを冒すことなく、生成されたクラスにメソッドを追加する唯一の方法です。これは、テンプレート生成(T4)コード、ORMなどで便利です。
サービス参照は、生成されたコードをユーザーが作成したコードから分離するために部分クラスが役立つもう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..
}
ほとんどの人partial
は、生成されたコードファイルがあるクラスまたはインターフェイスにのみ使用する必要があると述べています。私は同意しません、そしてここに理由があります。
1つの例として、C#のSystem.Mathクラスを見てみましょう。それはclassです。70以上のメソッドをすべて同じ単一のコードファイルに詰め込もうとはしません。維持するのは悪夢です。
各数学メソッドを個別の部分クラスファイルに配置し、すべてのコードファイルをプロジェクトのMathフォルダーに配置すると、整理が大幅に簡単になります。
同じことが、多様な機能を大量に持つ他の多くのクラスにも当てはまります。たとえば、PrivateProfile APIを管理するためのクラスは、単一のプロジェクトフォルダー内の部分クラスファイルのクリーンなセットに分割されることでメリットが得られる場合があります。
個人的には、ほとんどの人が「ヘルパー」または「ユーティリティ」クラスと呼ぶものを、メソッドまたはメソッド機能グループごとに個別の部分ファイルに分割します。たとえば、あるプロジェクトでは、文字列ヘルパークラスにほぼ50のメソッドがあります。これは、リージョンを使用しても、長く扱いにくいコードファイルになります。メソッドごとに個別の部分クラスファイルを使用すると、保守が大幅に簡単になります。
これを行うときは、部分クラスの使用に注意し、プロジェクト全体ですべてのコードファイルのレイアウトを統一します。たとえば、クラスのパブリック列挙型とクラスのプライベートメンバーをCommon.csまたは同様の名前のファイルに配置し、それらが含まれている部分的なファイルのみに固有でない限り、ファイル全体に分散させるのではなく、
クラスを個別のファイルに分割すると、現在のファイルの2つの異なるセクションを同時に表示できるテキストエディターのスプリッターバーも使用できなくなることに注意してください。
部分クラスを使用すると、ソースファイルを追加するだけで、適切に設計されたプログラムに機能を追加できます。たとえば、ファイルインポートプログラムは、既知のファイルを処理するモジュールを追加することで、それらを追加するように設計できます。たとえば、メインのファイルタイプコンバーターには小さなクラスを含めることができます。
部分的なパブリッククラスzzFileConverterRegistrar イベントレジスター(ByVal mainConverter as zzFileConverter) Sub registerAll(ByVal mainConverter as zzFileConverter) RaiseEventレジスター(mainConverter) End Sub 終了クラス
1つ以上のタイプのファイルコンバーターを登録する各モジュールには、次のようなものが含まれます。
部分的なパブリッククラスzzFileConverterRegistrar Private Sub RegisterGif(ByVal mainConverter as zzFileConverter)がMe.Registerを処理する mainConverter.RegisterConverter( "GIF"、GifConverter.NewFactory)) End Sub 終了クラス
メインファイルコンバータークラスは「公開」されていないことに注意してください。アドインモジュールがフックできる小さなスタブクラスを公開するだけです。名前の競合のわずかなリスクがありますが、各アドインモジュールの「レジスタ」ルーチンが、処理するファイルのタイプに応じて名前が付けられている場合は、おそらく問題になりません。そのようなことが心配な場合は、登録サブルーチンの名前にGUIDを付けることができます。
編集/補遺 明確に言うと、これの目的は、さまざまな個別のクラスがメインプログラムまたはクラスにそれらを知らせる手段を提供することです。メインファイルコンバーターがzzFileConverterRegistrarで行う唯一のことは、そのインスタンスを1つ作成し、RegisterAllメソッドを呼び出して、Registerイベントを発生させることです。そのイベントをフックしたいモジュールは、それに応答して任意のコードを実行できます(それが全体のアイデアです)が、他の名前と一致する名前のメソッドを定義する以外に、zzFileConverterRegistrarクラスを不適切に拡張することでモジュールができることはありません。不適切に作成された拡張機能が別の不適切に作成された拡張機能を破壊する可能性は確かにありますが、その解決策は、拡張機能を破壊したくない人が単純に適切に書き込むことです。
部分クラスを使用せずに、メインファイルコンバータークラス内のどこかに、次のようなコードを含めることができます。
RegisterConverter( "GIF"、GifConvertor.NewFactory) RegisterConverter( "BMP"、BmpConvertor.NewFactory) RegisterConverter( "JPEG"、JpegConvertor.NewFactory)
ただし、別のコンバーターモジュールを追加するには、コンバーターコードのその部分に入り、新しいコンバーターをリストに追加する必要があります。部分的な方法を使用すると、これは不要になりました。すべてのコンバーターが自動的に含まれます。
IModule
インターフェースを実装するだけではどうですか?
IModule
、あなたはMEF(多くのちょうど1)、などなどのようなプラグイン・フレームワークを使用することができます
部分クラスは最近、複数の開発者が1つのファイルに追加するソース管理を支援し、新しいメソッドがファイルの同じ部分に追加されました(Resharperによって自動化)。
これらのgitへのプッシュにより、マージの競合が発生しました。新しいメソッドを完全なコードブロックとして受け取るようにマージツールに指示する方法が見つかりませんでした。
この点で部分クラスを使用すると、開発者は自分のファイルのバージョンに固執することができ、後で手動でマージすることができます。
例-
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 { }
}
以下は、部分クラスのいくつかの利点のリストです。
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エンティティ間のマッピングには影響しますが、追加のフィールドを簡単に取得できます。つまり、システムが生成したコードをいじることなく、自分でコードを記述できるということです。
複数の開発者がクラスのコードを同時に書くことができます。
大きなクラスを圧縮することにより、アプリケーションをよりよく維持できます。インターフェースの実装に応じて複数のソースファイルを作成できるように、複数のインターフェースを持つクラスがあるとします。ソースファイルに部分クラスがある実装されたインターフェースを理解し、維持することは簡単です。
重要なサイズ/複雑さのネストされたクラスを含むクラスがあるときはいつでも、クラスにマークpartial
を付け、ネストされたクラスを別のファイルに入れます。[クラス名]。[ネストされたクラス名] .csというルールを使用して、ネストされたクラスを含むファイルに名前を付けます。
次のMSDNブログでは、保守性のためにネストされたクラスで部分クラスを使用する方法について説明しています。http://blogs.msdn.com/b/marcelolr/archive/2009/04/13/using-partial-classes-with-nested-classes-for- maintenanceability.aspx
私はこの質問が本当に古いことを知っていますが、部分クラスに私の見解を追加したいと思います。
私が部分クラスを個人的に使用する1つの理由は、プログラム、特にステートマシンのバインディングを作成するときです。
たとえば、OpenGLはステートマシンであり、すべてグローバルに変更できるメソッドのヒープがありますが、私の経験では、非常に多くのメソッドが存在するOpenGLに似たものをバインドすると、クラスは容易に10k LOCを超える可能性があります。
部分的なクラスは、私のために、このダウンを破るだろうと迅速な方法を見つけることで私を助けて。
部分クラスは主にコードジェネレーターを支援するために導入されているため、私たち(ユーザー)は、ASP.NETの.designer.csクラスのような生成されたクラスへのすべての作業/変更を失うことなく、生成するほとんどすべての新しいツールを生成しますコードLINQ、EntityFrameworks、ASP.NETは生成コードに部分クラスを使用するため、部分クラスとメソッドを利用してこれらの生成コードのロジックを安全に追加または変更できますが、部分クラスを使用して生成コードに要素を追加する前に十分に注意してくださいビルドを中断すると簡単ですが、ランタイムエラーが発生すると最悪です。詳細については、こちらを確認してくださいhttp://www.4guysfromrolla.com/articles/071509-1.aspx
私は答えで明確に見つけることができなかった2つの使用法に注意します。
一部の開発者は、コメントを使用してクラスのさまざまな「部分」を分離しています。たとえば、チームは次の規則を使用する場合があります。
public class MyClass{
//Member variables
//Constructors
//Properties
//Methods
}
部分クラスを使用すると、さらに一歩進んで、セクションを個別のファイルに分割できます。慣例として、チームは各ファイルにそれに対応するセクションのサフィックスを付ける場合があります。したがって、上記ではMyClassMembers.cs、MyClassConstructors.cs、MyClassProperties.cs、MyClassMethods.csのようなものになります。
他にも触れたように、クラスを分割する価値があるかどうかは、この場合のクラスの大きさによって異なります。小さい場合は、すべてを1つのマスタークラスに含める方が簡単です。ただし、これらのセクションのいずれかが大きくなりすぎた場合は、マスタークラスを適切に保つために、そのコンテンツを別の部分クラスに移動できます。その場合の慣例として、セクション見出しの後に「部分クラスを参照」のようなコメントを残すことが挙げられます。例:
//Methods - See partial class
これはおそらくまれなことですが、使用するライブラリの2つの関数の間に名前空間の衝突がある可能性があります。単一のクラスでは、多くの場合、これらのいずれかにusing句を使用できます。その他の場合は、完全修飾名またはエイリアスが必要です。部分クラスでは、各名前空間とusingステートメントのリストが異なるため、2つの関数セットを2つの別々のファイルに分けることができます。
using Library1 = The.Namespace.You.Need
かglobal::Root.Of.Namespace