質問
ではありません一般 ICloneable<T>
存在しない?
う快適なものまねばならないことは起こらないキャストで見たクローンもの。
解決
ICloneableは、今悪いAPIと考えられています。私は、彼らがこのインタフェースを改善しない理由、これがあると思います。
あなたはおそらく、入力されたクローン拡張メソッドを行うことができますが、私は、拡張メソッドは、元のものよりも低い優先順位を持っているので、それは別の名前が必要になると思います。
他のヒント
(私は同意する、1)アンドレイの応答に加えて - ICloneable
はのあるの行われたとき、あなたはまた、公共Clone()
は、型指定されたオブジェクトを返す作るために、明示的な実装を選択することができます:
public Foo Clone() { /* your code */ }
object ICloneable.Clone() {return Clone();}
はもちろん、一般的なICloneable<T>
と第二の問題がある - 。相続
私が持っている場合:
public class Foo {}
public class Bar : Foo {}
そして、私はICloneable<T>
を実施し、その後、私はICloneable<Foo>
を実装していますか? ICloneable<Bar>
?あなたはすぐに、同一のインタフェースの多くの実装を開始します...
キャストと比較...、それは本当にそんなに悪いのですか?
私はの他のそれを実装するよりも、あなたがインターフェイスで正確に何をしますか、依頼する必要がありますか?あなたがそれにキャストするときのインターフェイス(つまり、このクラスのサポート「IBAR」ん)、またはパラメータまたはそれを取るセッターを持っている(つまり、i「はIBAR」を取る)、一般的にのみ有効です。 ICloneableで - 私たちは、全体のフレームワークを経て、それの実装以外の何かだったどこにでも単一の使用を見つけることができませんでした。我々はまた、それを実装するよりも、他の何かをする「現実世界」のいずれかの使用法を見つけることができなかったしました(私たちはへのアクセス権を持っている〜60,000のアプリで)ます。
あなたはちょうどあなたがあなたの「複製可能」オブジェクトを実装するパターンを強制したい場合は今、それは完全に罰金使い方だ - と先に行きます。また、「クローニング」(すなわち深いか浅い)あなたに意味を正確に何を決定することができます。ただし、その場合には、それを定義するために、私たちは必要(BCL)はありません。無関係なライブラリ間の抽象化として型指定されたインスタンスを交換する必要があるときに我々は唯一のBCLで抽象化を定義します。
デビッド・キーン(BCLチーム)
私は質問は「なぜ」無用だと思います。そこに非常に便利ですインタフェース/クラスの/ etc ...がたくさんありますが、.NET Frameworkuベースライブラリの一部ではありません。
しかし、主に、あなたはそれを自分で行うことができます。
public interface ICloneable<T> : ICloneable {
new T Clone();
}
public abstract class CloneableBase<T> : ICloneable<T> where T : CloneableBase<T> {
public abstract T Clone();
object ICloneable.Clone() { return this.Clone(); }
}
public abstract class CloneableExBase<T> : CloneableBase<T> where T : CloneableExBase<T> {
protected abstract T CreateClone();
protected abstract void FillClone( T clone );
public override T Clone() {
T clone = this.CreateClone();
if ( object.ReferenceEquals( clone, null ) ) { throw new NullReferenceException( "Clone was not created." ); }
return clone
}
}
public abstract class PersonBase<T> : CloneableExBase<T> where T : PersonBase<T> {
public string Name { get; set; }
protected override void FillClone( T clone ) {
clone.Name = this.Name;
}
}
public sealed class Person : PersonBase<Person> {
protected override Person CreateClone() { return new Person(); }
}
public abstract class EmployeeBase<T> : PersonBase<T> where T : EmployeeBase<T> {
public string Department { get; set; }
protected override void FillClone( T clone ) {
base.FillClone( clone );
clone.Department = this.Department;
}
}
public sealed class Employee : EmployeeBase<Employee> {
protected override Employee CreateClone() { return new Employee(); }
}
これは書くには非常に簡単ですあなたがそれを必要とする場合は、自分自身をのインタフェースます:
public interface ICloneable<T> : ICloneable
where T : ICloneable<T>
{
new T Clone();
}
そしてこの最近の記事 なぜオブジェクトのコピーは酷いものですか?, あまり多くなかったように思い質問のニーズを追加clafirication.その他の回答をこちらで良いと言ってもその答えは完全ではないのかな ICloneable<T>
?
用途
だからクラスを実装します。以前からいた方法のた
ICloneable
, ので、現在は一般に受け入れICloneable<T>
.する必要がある編集することができます。その後、手法かどうかをチェックしますオブジェクト
is ICloneable
.何を?できないis ICloneable<>
どんなオブジェクトの型でコンパイルタイプであるかのように映像化している方のクラスを提供します。.最初の実際問題です。る必要があります両方の
ICloneable<T>
やICloneable
, は、元の実施を後になります。このように、実務者が実施する必要性の両方の方法-object Clone()
やT Clone()
.いいえ、おかげさまで十分に楽しくIEnumerable
.既に指摘もあるが複雑化の継承関係を示します。が共分散がこの問題を解決するには、派生タイプの実施が必要
ICloneable<T>
独自のタイプ、もしものメソッドを同じ署名(パラメータは基本的に)、Clone()
の基底クラスです。お新しいクローンのメソッドのインターフェイスが明示的に無意味が失われまでの活用お求の作成時にICloneable<T>
.その追加new
キーワードとなります。がることを忘れないでくださいますようにオーバーライドベースのクラス'Clone()
(実施が不均一のためのすべての派生クラス、すなわちに同じオブジェクトを返すから毎クローンの方法、基準クローンの方法をvirtual
)!が、残念ながら、できないもoverride
やnew
方法と同じ署名を表します。選択の最初のキーワードか、失点しておきたい場合の追加ICloneable<T>
.Chossingのまえに、プレスリリースを、メソッドを同じ異なるオブジェクト。点
したい
ICloneable<T>
より快適に、も快適なインタフェース設計のため、その意味は(一般OOP)統一のための行動のオブジェクト(がクライアントまで、フルのC#では統一し、外側の行動、などの方法や性質は、その働き).が第一の理由だと確信しきれなのに、できるオブジェクト
ICloneable<T>
でも未定の範囲に限定するタイプから返されるクローン法です。しかし、手にプログラマで実施ICloneable<T>
ここでTはないし、その徹底することです。なので、達成のための制限を追加することができます素敵な制約の汎用パラメータ:
public interface ICloneable<T> : ICloneable where T : ICloneable<T>
く制限のなwhere
, だができな制限すること T は、その実施はインターフェース(おに導き出すことができるからICloneable<T>
異なるタイプを実装します。すでも、この目的のできない達成の
ICloneable
また失敗したこと、インターフェースでの真の制限の挙動の実施を行っています。-
ご覧の通り、この証明の汎用インタフェースはハードに完全に実施するととも本当に不要になったとは絶対に無駄にはなりません。
ものの、何かを探して快適にクローニングするオブジェクトです。るには二つの方法がありますか
追加方法
public class Base : ICloneable
{
public Base Clone()
{
return this.CloneImpl() as Base;
}
object ICloneable.Clone()
{
return this.CloneImpl();
}
protected virtual object CloneImpl()
{
return new Base();
}
}
public class Derived : Base
{
public new Derived Clone()
{
return this.CloneImpl() as Derived;
}
protected override object CloneImpl()
{
return new Derived();
}
}
このソリューションも快適動作をユーザーにも長すぎます。まないの"快適"の方法を返し現在でも簡単にで public virtual object Clone()
.
そを見てみましょう"究極の"ソリューションは何にでもマージエレメントはintentedによ(笑)。
延長!
public class Base : ICloneable
{
public virtual object Clone()
{
return new Base();
}
}
public class Derived : Base
{
public override object Clone()
{
return new Derived();
}
}
public static T Copy<T>(this T obj) where T : class, ICloneable
{
return obj.Clone() as T;
}
この名前 コピー ぶつからない、現在の クローン 方法(コンパイラの好みのタイプ独自の宣言方法は以上に延長。の class
制約がありますのでご速度を必要としませんnullチェック。
これを明確にした理由はしない ICloneable<T>
.しかし、しないことをお勧めしますの実施 ICloneable
ます。
この問題は非常に古い(5年からこの回答とした答えが見つかりこの条項という問いに対する答えるもので こちらの
編集:
こちらの見積もりから、回答の問題について"を必ずご確認ください全ての記事でその他の興味深いこと):
多くのインターネットを指2003年のブログ によるブラッド-アブラムスは、雇用-マイクロソフトリサーチ-あ 考えるICloneableを検討します。のブログです このアドレス: 実施ICloneable.ものの誤解を招く タイトルのこのブログで通話を実施しないICloneableを中心に 遠浅のため/深層混乱した。第終了直 提案:が必要な場合は、クローニング機構を明らかにし、ご自身のクローン、または コピー方法論、およびこの文書は明確であるかどうか 深さは浅いコピーします。適切なパターン:
public <type> Copy();
の大きな問題は、彼らが同じクラスであるTを制限することができなかったということです。フォアの例にこれをやってからあなたを防ぐだろうか。
interface IClonable<T>
{
T Clone();
}
class Dog : IClonable<JackRabbit>
{
//not what you would expect, but possible
JackRabbit Clone()
{
return new JackRabbit();
}
}
彼らのようなパラメータの制限を必要とします:
interfact IClonable<T> where T : implementing_type
これは非常に良い質問です...あなたがあなた自身の作ることができ、しかします:
interface ICloneable<T> : ICloneable
{
new T Clone ( );
}
アンドレイは、それが悪いAPIと考えていますと言うが、私は非推奨になってきて、このインターフェイスについては何も聞いていません。そして、それはインターフェースのトンを壊します... Cloneメソッドは浅いコピーを実行する必要があります。 オブジェクトはまた、ディープコピー、(BOOL深い)オーバーロードされたクローンを提供する場合に使用することができる。
EDIT:私はオブジェクト「クローニング」に使用するパターンは、コンストラクタでプロトタイプを通過する
class C
{
public C ( C prototype )
{
...
}
}
これは、任意の潜在的な冗長コードの実装状況を取り除きます。 ところで、ICloneableの限界について話して、それが浅いクローンまたは深いクローン、あるいは一部が浅い/深い一部のクローンは、実施すべきかどうかを決定するために、実際にオブジェクト自体次第ではないでしょうか?私たちは本当に限り、意図したとおりにオブジェクトが動作するよう、気にする必要がありますか?いくつかの場面では、優れたクローンの実装は非常によく浅いと深いクローンの両方が含まれる場合があります。