「this」キーワードはいつ使用しますか?[閉まっている]


249

他の人がthisキーワードをどのように使用するのか知りたくて。コンストラクターで使用する傾向がありますが、クラス全体で他のメソッドで使用することもできます。いくつかの例:

コンストラクタで:

public Light(Vector v)
{
    this.dir = new Vector(v);
}

他の場所

public void SomeMethod()
{
    Vector vec = new Vector();
    double d = (vec * vec) - (this.radius * this.radius);
}

2
MSDNで本当に必要 なときに良い例を見つけましたthisこのリンクに従ってください ... ;-)
Matt

12
誰かを理解して最適化または書き直す必要がある場合、ほとんどが不十分に記述されたコードthisまたは他の修飾子を使用すると、変数のスコープがわかります(特に省略された定数のクラス修飾子(同じパッケージまたは階層)またはsuper/ base修飾子)。そして、一般的に使用されるような構文を使用する_fooことは、私にとってはそれほどエレガントに思えません。intellisense _を押すことは、入力するよりも時間がかかりthisます。そして、なぜそんなに迷惑をかけるのか!Eclipseの自動保存フォーマット機能を使用すると_、修飾子を忘れた場合に必要ありません。
djmj

6年以内に更新されていないこのキーワードについて、以下の回答とコメント、およびMSDNドキュメントdocs.microsoft.com/en-us/previous-versions/visualstudio/…を読んだ後、お勧めしますthisキーワードを使用しないようにします。それは無意味です。パラメータを同じ名前にしないでください。混乱を招き、愚かになります。どうしてそうするか?また、thisの使用時にインスタンスを渡さないでください。混乱を招き、愚かになります。
Yusha

回答:


218

C#では、このキーワードの使用法がいくつかあります。

  1. 類似の名前で非表示になっているメンバーを修飾するには
  2. オブジェクトが他のメソッドにパラメーターとして自分自身を渡すようにするには
  3. オブジェクトがメソッドから自分自身を返すようにするには
  4. インデクサーを宣言するには
  5. 拡張メソッドを宣言するには
  6. コンストラクター間でパラメーターを渡すには
  7. 値タイプ(構造体)値を内部的に再割り当てします
  8. 現在のインスタンスで拡張メソッドを呼び出すには
  9. 自分自身を別の型にキャストするには
  10. 同じクラスで定義されたコンストラクターをチェーンするには

スコープ内に同じ名前のメンバー変数とローカル変数を持たないことで最初の使用を回避できます。たとえば、一般的な命名規則に従い、フィールド(キャメルケース)ではなくプロパティ(パスカルケース)を使用して、ローカル変数(ラクダ)との衝突を回避します。場合)。C#3.0では、自動実装プロパティを使用してフィールドをプロパティに簡単に変換できます


49
8.現在のインスタンスで拡張メソッドを呼び出す(this.Foo();動作しますが動作しFoo()ません)
マークグラベル

4
また、それ自体を別の型にキャストするには、たとえば、明示的に実装されたメソッドがのように呼び出され((ICollection<T>)this).Add(bla)ます。
nawfal 2013年

4
同じ型で定義された別のコンストラクターに構築をチェーンします。 public ClassName(...) : this(...)
Lasse V. Karlsen、2014

1
@Anandは、実行時のパフォーマンスにはまったく影響しません。あいまいさがないと仮定すると、コンパイラーの出力は、たとえばthis.someField = someValueまたはのように書くかどうかに関係なく同じですsomeField = someValue。コンパイラはソースコードを異なる方法で解析するため、コンパイラのパフォーマンスに影響を与える可能性がありますが、違いは無視できます。
phoog

7
プロパティをパラメーターと同じ名前にすることができないスタイルの規則に準拠している場合にのみ、プロパティを介してフィールドにアクセスすることにより、最初の問題を回避できます。 普及しているC#スタイルの規則がその要件を満たしているだけです。ただし、すべてのC#がその規則に従って記述されているわけではありません。thisキーワード自体を不要にするプロパティ自体には固有のものは何もありません。呼び出されたコンストラクタパラメータは、そのメンバーがフィールド、プロパティ、またはイベントのいずれであるかに関係なく、そのメンバーxを非表示xにします。
phoog

246

これがくしゃくしゃに聞こえるという意味ではありませんが、それは問題ではありません。

真剣に。

プロジェクト、コード、仕事、私生活など、重要なことを見てください。フィールドへのアクセスを修飾するために「this」キーワードを使用するかどうかに依存して、それらの成功はありません。thisキーワードは、時間どおりに出荷するのに役立ちません。バグを減らしたり、コードの品質や保守性に大きな影響を与えたりすることはありません。昇給したり、オフィスで過ごす時間を短縮したりすることはできません。

それは本当にただのスタイルの問題です。「これ」が好きなら、それを使ってください。そうでない場合は、しないでください。正しいセマンティクスを取得する必要がある場合は、それを使用してください。真実は、すべてのプログラマーが独自の独自のプログラミングスタイルを持っていることです。そのスタイルは、「最も美的に満足のいくコード」がどのように見えるべきかという特定のプログラマーの概念を反映しています。定義により、コードを読み取る他のプログラマーは、異なるプログラミングスタイルを使用することになります。つまり、他の人が気に入らない、または違ったことをしたことは常にあります。ある時点で、誰かがあなたのコードを読んで何かについて不平を言うでしょう。

私はそれを心配しません。自分の好みに応じて、コードが見た目に美しくなるようにします。10人のプログラマーにコードのフォーマット方法を尋ねると、約15の異なる意見が得られます。注目すべきより良いことは、コードがどのように因数分解されるかです。抽象化されたものは正しいですか?意味のある名前を付けましたか?コードの重複はたくさんありますか?単純化できる方法はありますか?これらのことを正しく行うことは、プロジェクト、コード、仕事、そして人生に最大のプラスの影響を与えると思います。偶然にも、それはおそらく他の人が少なくともつぶやくことも引き起こすでしょう。コードが機能し、読みやすく、十分に因数分解されている場合、他の人はフィールドを初期化する方法を詳しく調べません。彼はあなたのコードを使うだけで、その素晴らしさに驚嘆します。


35
thisキーワードは、意味的に意味があります。以下の@JasonBuntingのコメントを参照してください。のスタイルの使いすぎをthis実際の目的と混同します。あなたの発言は単なるばかげているだけではなく、それは間違っています!
Dan Barowy 2013年

12
機会があれば、私の答えをもう一度読んでください。正しいセマンティクスが必要な場合に使用することについて話します。また、出所の質問を確認することもできます。意味的に必要ではない例での使用を示しています。だから、私が言ったことが「間違った」とは正確にはわかりません。私の答えは確かに軽薄ではありません。
Scott Wisniewski 2013年

9
あなたの答えが私にとってどのように聞こえるか知っていますか?行の間に「どうやってこのような質問をする勇気がありますか?」と読みました。-それは私の考えでは本当に建設的ではありません。誰もがすべてを知っているわけではありません-これが私たちがStackoverflowを持っている理由です:他人を助け、助けを得るため。あなたが知っているいくつかのトピック、いくつかは他を知っています。お互いを助け、お互いに戦わないでください。考えてみてください。
マット

9
耳障りに聞こえるつもりはありませんが、これはこれまでのところ最悪の答えの1つです。これをあなたの仕事や私生活と比較することがどのように役立つかわかりません。他のものより重要でないものがあるからといって、それらが重要ではないという意味ではありません。一貫したプログラミングスタイルを持つことは重要ではありません(選択したコードの読みやすさ/保守性についての本を読んでください)。
aioobe 2015年

4
私の考えを誤解したかもしれません。「一貫したスタイルを持っている」ことは悪いことではありませんでした。その影響については何も言わない。それは、「私のスタイルガイドは「これ」を義務付けるべきか」というopの質問です。すべてのフィールドアクセスのプレフィックスとして?」恣意的で気まぐれです。
Scott Wisniewski、2015年

96

絶対に必要な場合、つまり別の変数が別の変数をシャドウしている場合にのみ使用します。ここのような:

class Vector3
{
    float x;
    float y;
    float z;

    public Vector3(float x, float y, float z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

}

または、Ryan Foxが指摘するように、これをパラメーターとして渡す必要があります。(ローカル変数はメンバー変数よりも優先されます)


6
この場合、コンストラクタの入力変数に異なる名前を付けないのはなぜですか?
wz366 2018年

54

個人的には、メンバー変数を参照するときに常にこれを使用するようにしています。コードを明確にし、読みやすくします。あいまいさがなくても、私のコードを初めて読んだ人はそれを知りませんが、これが一貫し使用されているのを見ると、メンバー変数を見ているかどうかがわかります。


9
しかし、いつか使用するのを忘れた場合、混乱してしまいます
2011

2
追加のスタイルチェックによって回避できる@surfen。たとえば、JavaではCheckstyleを使用して、フルビルドの後に実行できます(そして一般的な反復/ OO言語では、同様のツールがあります)
Maarten Bodewes

5
あいまいな場合にそれを忘れたかのように@surfen。「でもあなたが忘れたら...」と言って、私はどんな議論も破ることができます。
Askolein 2014年

6
ほとんどの人は、他人のコードを決して読んだり、最適化したり、書き直したりしていないようです!予選は時間とモチベーションのセーバーです!修飾子がないと、コードの任意の行が表示されれば魔法のようになります。したがって、これらの変数がどこから来ているのかをチェックインするだけで、常に時間を浪費することになります。
djmj

3
私はこれが非常に古い投稿であることを知っていますが、この答えの皮肉(私がたまたま同意する)についてコメントせざるを得ません。邪悪なハンガリー記法に対するジハードでは、メンバー変数の前に "m_"を付けることを敢えてした人は、メンバー変数を区別するだけでは役に立たなかったり必要なかったりしたため、すぐに頭を悩ませました。
マイケルJ.

38

必要がない場合でも、インスタンス変数を参照するたびに使用します。コードがより明確になると思います。


クラス変数をできる限り区別したいので、コードがより明確になります。以前は、プライベート文字列m_nameなどの接頭辞m_(メンバー変数)を使用していました。今、これを使用します。たとえば、クラスTest {private string a; public someMethod(){this.a = "foo"; }}
ブロードバンド

36

いつも使うのが「ベストプラクティス」などと言う人すべてが信じられない。

Coreyの例のように曖昧な場合や、Ryanの例のようにオブジェクトをパラメータとして渡す必要がある場合は、「this」を使用します。スコープチェーンに基づいて変数を解決できることは十分明確である必要があるため、それを使用して変数を修飾する必要がないため、他の方法で使用する理由はありません。

編集:「this」に関するC#のドキュメントは、「this」キーワードについて、私が言及した2つに加えて、インデクサーを宣言するためのもう1つの使用法を示しています

編集:@フアン:ええと、ステートメントに矛盾はありません-「this」キーワードを使用する場合(C#のドキュメントに記載されているように)は3つのインスタンスがあり、実際にそれが必要な場合があります。シャドウイングが行われていないときにコンストラクターの変数の前に「this」を貼り付けることは、キーストロークの無駄であり、それを読み取るときの私の時間の無駄であり、メリットはありません。


21
@ JasonBunting:あなたは時々何かをすることができ、他の人にはできない...それは混乱します... あなたのコードで働かないこと望みますあなたは将来あなたのコードを読む人があなたのことを理解するだろうといつも仮定することはできません書いて、あなたは可能な限り明確な、そしてそれを達成するための一つの方法は、一貫性があるとする必要が
フアン

@ juan、10年後。あなたはまだ「これ」を使うのは良い習慣だと思いますか?:)
Scott Adams

2
@ScottAdams私はまだ一貫性と明快さを信じています、はい
juan

変数を見ただけで、変数のスコープ(ローカル変数かメンバー変数か)を判断するのはどうですか?「これ」はこの目的のために正当化されていませんか?あるいは、より小さなメソッドを記述すれば、とにかく変数のスコープを理解するのは簡単だと言うつもりですか?
BornToCode

27

StyleCopから指示されたときに使用します。StyleCopに従う必要があります。そうそう。


1
そしてReSharperは私にそれを使わないように言っています。StyleCopとReSharperの両方を同時に使用しているときは、ちょっと混乱します:)しかし、上記のCoreysの回答に頼り、絶対に必要な場合にのみ「this」キーワードを使用します。
Gunnar 2013年

@Gunnar、冗長な「これ」を取り除くことを無効にするオプションがあります。R#で
Winger Sendon、2016

@EmperorAiman-はい、知っています。私のポイントは、これらの2つの一般的なフォーマットツールはデフォルトで2つの異なることを示唆しており、混乱を招く可能性があるということでした。「するべきか否か...」:)
Gunnar

11

現在のオブジェクトへの参照が必要なときはいつでも。

特に便利なシナリオの1つは、オブジェクトが関数を呼び出していて、それを関数に渡したい場合です。

例:

void onChange()
{
    screen.draw(this);
}

7

私が扱っているのはインスタンスメンバーであることを明確にするためだけに、どこでも使用する傾向があります。


5

私は曖昧さがありそうなところならどこでもそれを使用します(明らかに)。コンパイラのあいまいさ(その場合は必要になります)だけでなく、コードを見ている人にとってもあいまいさがあります。


5

thisキーワードのもう少しまれな使用法は、実装クラス内から明示的なインターフェース実装を呼び出す必要がある場合です。これは不自然な例です:

class Example : ICloneable
{
    private void CallClone()
    {
        object clone = ((ICloneable)this).Clone();
    }

    object ICloneable.Clone()
    {
        throw new NotImplementedException();
    }
}

4

ここで私はそれを使用します:

  • クラス内からプライベートメソッドにアクセスする(区別するため)
  • 現在のオブジェクトを別のメソッドに渡す(またはイベントの場合は送信者オブジェクトとして)
  • 拡張メソッドを作成するとき:D

私はプライベートフィールドの変数名の前にアンダースコア(_)を付けるため、これをプライベートフィールドには使用しません。


4

[C ++]

「必要なときに使う」旅団に同意します。これでコードを不必要に装飾することは良い考えではありません。コンパイラが警告をしなくても警告を表示しないからです。これは、これが常に存在することを期待する人々に潜在的な混乱をもたらします。つまり、彼らはそれについて考えなければならないでしょう。

では、いつそれを使用しますか?私はいくつかのランダムなコードを見回したところ、これらの例が見つかりました(これらが良いことかそうでないかについて、私は判断を下していません):

  • 関数に「自分」を渡す。
  • 「自分」をポインタなどに割り当てる。
  • キャスティング、つまりアップ/ダウンキャスティング(安全またはその他)、constnessのキャストなど
  • コンパイラーは明確化を強制しました。

3

常に使用する必要があります。私はプライベートフィールドとパラメーターを区別するために使用します(私たちの命名規則では、メンバー名とパラメーター名に接頭辞を使用しないと記載されているため(そしてそれらはインターネット上で見つかった情報に基づいているため、ベストプラクティス))


3

同じタイプのオブジェクトへの参照を受け入れる関数で、どのオブジェクトをどこで参照している完全に明確にしたいときに使用します。

例えば

class AABB
{
  // ... members
  bool intersects( AABB other )
  {
    return other.left() < this->right() &&
           this->left() < other.right() &&

           // +y increases going down
           other.top() < this->bottom() &&
           this->top() < other.bottom() ;
  }
} ;

(対)

class AABB
{
  bool intersects( AABB other )
  {
    return other.left() < right() &&
           left() < other.right() &&

           // +y increases going down
           other.top() < bottom() &&
           top() < other.bottom() ;
  }
} ;

AABBがright()参照する一目で?this清澄のビットを付加します。


3

JakubŠturcの回答では、コンストラクター間でのデータの受け渡しに関する彼の#5は、おそらく少しの説明を使用できるでしょう。これはコンストラクターのオーバーロードであり、使用thisが必須である1つのケースです。次の例では、デフォルトパラメータを使用して、パラメータなしのコンストラクタからパラメータ化されたコンストラクタを呼び出すことができます。

class MyClass {
    private int _x
    public MyClass() : this(5) {}
    public MyClass(int v) { _x = v;}
}

これは特に便利な機能である場合があります。


2

Visual C ++で自由に使用する習慣がついたので、 '>'キーを押すとIntelliSenseがトリガーされ、怠惰になります。(そしてタイプミスが起こりやすい)

しかし、グローバル関数ではなくメンバー関数を呼び出していることがわかると便利なので、引き続き使用しました。


1

私は_でフィールドに下線を引く傾向があるので、これを実際に使用する必要はありません。また、R#はとにかくそれらをリファクタリングする傾向があります...


1

私はほとんど同じタイプの内部からタイププロパティを参照するときにのみこれを使用します。別のユーザーが言ったように、私はローカルフィールドにも下線を引いているので、これを必要とせずに目立つようになります。


1

単一の引数の多相性のために片側のメソッドに配置する必要がある対称演算を除いて、必要な場合にのみ使用します。

boolean sameValue (SomeNum other) {
   return this.importantValue == other.importantValue;
} 

1

[C ++]

これは、ほとんどの場合、次のような奇妙な(意図しない、危険、またはプログラムの時間の無駄)をチェックして防止する必要がある代入演算子で使用されます。

A a;
a = a;

割り当て演算子が記述されます。

A& A::operator=(const A& a) {
    if (this == &a) return *this;

    // we know both sides of the = operator are different, do something...

    return *this;
}

1

this C ++コンパイラ

C ++コンパイラは、シンボルがすぐに見つからない場合に、黙ってそのシンボルを検索します。時々、ほとんどの場合、それは良いことです:

  • 子クラスでオーバーロードしなかった場合は、母クラスのメソッドを使用します。
  • 型の値を別の型に昇格させる

しかし、時々、コンパイラに推測させたくないだけです。コンパイラが正しいシンボルをピックアップし、別のシンボルをピックアップしないようにします。

私にとって、それらの時は、メソッド内で、メンバーメソッドまたはメンバー変数にアクセスしたいときです。のprintf代わりに書いたからといって、ランダムなシンボルをピックアップしたくありませんprintthis->printfコンパイルされなかったでしょう。

ポイントは、Cレガシーライブラリ(§)、何年も前に書かれたレガシーコード(§§)、またはコピー/貼り付けが廃止されたがまだアクティブな機能である言語で起こり得ることで、コンパイラーに再生しないように指示することです機知は素晴らしいアイデアです。

これらが私が使用する理由ですthis

(§)まだ謎ですが、ソースに<windows.h>ヘッダーを含めることが、従来のすべてのCライブラリシンボルがグローバルネームスペースを汚染する理由なのでしょうか。

(§§)「ヘッダーを含める必要がありますが、このヘッダーを含めると、一般的な名前のダムマクロが使用されるため、コードが破損します」というのは、コーダーの人生におけるロシアのルーレットの瞬間の1つです。


1

'この。' 多数のメンバーを持つ「this」クラスのメンバーを見つけるのに役立ちます(通常、継承チェーンが深いため)。

タイプも含まれているため、CTRL + Spaceを押しても問題は解決しません。where-として「これ」。メンバーのみが含まれます。

私は通常、自分が求めていたものを手に入れたら削除しますが、これは私のスタイルの突破口です。

スタイルの面では、あなたが孤独なレンジャーであるなら、あなたが決める; あなたが会社で働いているなら、会社の方針に固執してください(ソース管理のことを見て、他の人が何をしているかを見てください)。メンバーの資格取得に使用するという点では、どちらも正しいか間違っています。間違っているのは一貫性のなさだけです。それがスタイルの黄金律です。ほんの少しだけ摘み取ったままにしておきます。代わりに、実際のコーディング問題(そして明らかにコーディング)について熟考してください。


1

できる限り使用しています。これにより、コードが読みやすくなり、コードが読みやすくなると、バグが減り、保守性が向上します。


1

同じコードベースで作業する多くの開発者がいる場合、いくつかのコードガイドライン/ルールが必要です。私が作業する場所では、フィールド、プロパティ、およびイベントに「this」を使用することを考えました。

私にとっては、このようにするのは理にかなっています。クラス変数とメソッド変数を区別すると、コードが読みやすくなります。


0

それは私が働いているコーディング標準に依存します。インスタンス変数を示すために_を使用している場合、「this」は冗長になります。_を使用していない場合、これを使用してインスタンス変数を表す傾向があります。


0

JohnMcGと同じようにIntellisenseを呼び出すために使用しますが、完了したら「this->」を削除して消去します。私は、メンバー変数の前に「m_」を付けるというMicrosoftの規則に従っているので、ドキュメントのままにしておくのは冗長です。


0

1-一般的なJavaセッターイディオム:

 public void setFoo(int foo) {
     this.foo = foo;
 }

2-このオブジェクトをパラメーターとして使用して関数を呼び出す場合

notifier.addListener(this);

0

C ++でまだ言及されていない用途が1つあります。これは、独自のオブジェクトを参照したり、受け取った変数からメンバーを明確にしたりすることではありません。

を使用thisして、他のテンプレートから継承するテンプレートクラス内で、非依存名を引数依存名に変換できます。

template <typename T>
struct base {
   void f() {}
};

template <typename T>
struct derived : public base<T>
{
   void test() {
      //f(); // [1] error
      base<T>::f(); // quite verbose if there is more than one argument, but valid
      this->f(); // f is now an argument dependent symbol
   }
}

テンプレートは、2パスメカニズムでコンパイルされます。最初のパスでは、非引数の依存名のみが解決およびチェックされますが、依存名は一貫性についてのみチェックされ、実際にテンプレート引数を置き換えることはありません。

その段階では、型を実際に置き換えることなく、コンパイラーは何base<T>ができるかについての情報をほとんど持っていません(基本テンプレートを特殊化すると、それを完全に異なる型に、未定義の型にでも変換できることに注意してください)。 。この段階ではf、プログラマーderivedにとっては自然に思える非依存呼び出しは、コンパイラーが名前空間のメンバーとして、または名前空間を囲む際に見つけなければならないシンボルです(例では発生しません)。

解決策は、非依存名fを依存名に変えることです。これは、実装されているタイプを明示的に示すことで、いくつかの方法で実行できます(-をbase<T>::f追加するbase<T>と、シンボルが依存しT、コンパイラーはそれが存在すると想定し、2番目のパスの実際のチェックを延期します。引数の置換。

2番目の方法は、複数の引数または長い名前を持つテンプレートから継承する場合のより多くのソーターは、単にthis->記号の前にを追加することです。実装しているテンプレートクラスは引数に依存するため(それはから継承base<T>this->、引数に依存し、同じ結果が得られthis->fます。テンプレートパラメーターの置換後、2番目のラウンドでチェックされます。


-2

絶対に必要でない限り、「this」を使用しないでください。

不必要な冗長性に関連するペナルティがあります。あなたはそれが必要である限り正確に長く、もはやないコードのために努力するべきです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.