thisを書く派?書かない派?

  • 9
    Like
  • 5
    Comment

あすかです。
プログラミングしてる時、たまに気になる話を雑めに書いてみます。

(´・ω・`)

C#、VBやJavaなど、クラスベースのオブジェクト指向言語を前提にした話ですが、this(Me)を書いているプログラム、そうでないプログラムをよく見かけます。

例えば、thisを書くのは

this.Variable = 5;

で、thisを書かないのは

Variable = 5;

といった具合ですね。

一つことわっておくと、

public MyClass(int param)
{
    this.param = param;    // thisが必要
}

このような場面ではthisを書きます。文法上の制約ですから当たり前です。
今回は、このようなものではなく、thisを書かなくてもいい場面の話です。

thisを書くメリット

ちなみに私はthisを書く派です。

というのも、後でコードを読み返す時に、ローカル変数とフィールド変数の区別が一発で付くからです。
VSはthisを色分けしてくれますよね。
けっこう地味かもしれませんが、長いクラス(といっても500行を超えるようなクラスはめったに書きませんが)の一部分だけを読む時に、thisの存在はかなり役に立ちます。

他の人のコード読むときにも、thisつけてくれって思うことがよくあります。どれがフィールド変数なのか、どの変数がそのインスタンスの状態なのか、私は書いてないのですぐには分からないです。特にバカ長いメソッドで、よく読まずに勘違いしたまま修正しちゃうと、バグの原因になりかねません。つまりは、変数の影響範囲を手軽に把握したいです。(バカ長いクラスやメソッドの存在自体を減らしてほしいのが本音です)

私はC#のプログラムを書くにあたって、MSDNの命名規約を参考にしているのですが、
一般に、privateなフィールド変数はCamel形式(名前を小文字から始めること)、publicやprotectedにすることの多いプロパティはPascal形式(大文字から始めること)です。そして、メソッド内のローカル変数はCamelです。
フィールド変数とローカル変数が同じCamel形式ですから、thisを書かないと一発で区別つかないです。

私はMSDNの命名規約を独自解釈して、PropertyChanged発行時など、あるプロパティにラップされたフィールド変数は_(アンダースコア)で始めてます。というか、アンダースコアで始まらないフィールド変数を作ることが実はあまりないので、あまり使わないものには殊更thisをつけなければいけないなと。
裏を返すと私のクラスではプロパティやメソッドの参照が中心になります。どちらもPascalですよね。それでも、thisをつけたときのほうが見やすいです。thisの色分けがなくて、先頭が大文字なのか小文字なのかだけの話だったら、見逃してしまうこともよくあります。

Pascalなプロパティにわざわざthisをつけるのには、もう1つ事情があります。privateなフィールド変数を、やっぱこれ公開しようと思ってpublicなプロパティに昇格することも、その逆も、たまにあります。そのときに名前を変更してもVSは自動でthisをつけたり外したりしてくれないので、いちいち全部にthisをつけたり外したりしなきゃいけないなと。苦行です。大仏に丸投げしたい。

今回はC#の話ですが、Javaだとプロパティが存在しないこともあって、ほんとにCamelの山ですよね。Camelそのものですよね。JavaがCamelで、CamelがJavaですよね。でもCamelはCamelだけどJavaでなくCamelでもなくて、でもやっぱりCamelなんですよね。え、クラスの名前?クラスってなんだっけ?程度には顕著なのではと思います。おい先輩どもOOPしろや

staticはどうするのか

話ちょっとそれますが、thisを必ず書くぞということになったら、static変数にはthisがつけられないのでどうするか?ってなりますよね。普通に考えると、こういう書き方になります。

static class MyClass
{
    private static int staticVariable = 5;
    public static int Mul(int value)
    {
        MyClass.staticVariable *= value;
        return MyClass.staticVariable;
    }
}

でもこれ、クラス名の長さによっては冗長になったりするので、実際は書かないことが多いです。というか自分はstatic変数の存在自体好きではないので、シングルトンにすることが多いです。

それじゃあstaticなメソッドやプロパティはどうするのか?それも、クラス名を先にくっつけないことが多いです。ちょっとコードは読みづらいのですが、やっぱりクラス名長いとめんどいんですよね。

ほとんど先述のような書き方が原因ではありますが、staticでないクラスにおいてはstaticなメンバは必要最低限にして、どうしてもstaticメンバが多くなりそうならstaticクラス作ってそこにまとめてます。staticメソッドとインスタンスメソッドが混在してるクラスは、やっぱりVSのインテリセンスがややこしくなってまぎらわしいですね。どれがstaticでどれがインスタンスなんだと。名前がFromで始まるファクトリメソッド作るとか、どうしても必要なときを除いて、こうしてます。

thisを書くデメリット

thisを書くデメリット考えてみました。真っ先に思いつくのは、やっぱり書くのがめんどいこと。
そもそもVSは、Variableという変数をインテリセンス使って入力したいってなったとき、

this.

と書いた時点でインテリセンス出してくれますが、実はthisをつけなくても

va

とか書いた時点でインテリセンス出してくれます。
え、変数の先頭覚えてないとインテリセンス出せないからあかん?VS2017からは変数名の途中から入力してもちゃんとインテリセンス出してくれます。なので、変数の名前で一番特徴的なキーワードを覚えていればそれでOKになったんです。さすがMSの変態!

もう1つ付け加えると、インスタンスメソッドを、ああこれやっぱインスタンスの状態に依存しないし多態性を犠牲にするものでもないからstaticメソッドにしたいなーとなったときにthisが邪魔。あちこちのthisを削除しなければいけません。その逆もまた然り、あちこちにthisをつけなければいけません。めんどい。大仏に押し付けたい。

そもそも、thisをつけないという行為は、そのメンバがインスタンスメンバであるかstaticメンバであるかを抽象化している、という見方もできますね。なので、こういう変更が、thisを使うときよりも柔軟にできるわけです。

それから、this.を書くこと自体、行全体を長くしてるので、1行が画面内におさまらなくなったり。いちいち横スクロールしなければいけなくなったり。LINQ以外ではあまり見かけない光景かもしれませんが。

ていうかそもそも、VSはデフォルトで「不要なthisを書くな」みたいな動作をします(後述)。これがありますから、「あーthisを書かないのが普通なんだ」と単純に考えちゃう人が多いんじゃないかと思います。
それに、Javaのeclipseではデフォルトで、メソッドの仮引数、インスタンス変数、ローカル変数を色分けします。その設定に助けられてthisをつけない人も多いと思います。あすかはeclipse重いからTerapadだけどな

これ以外は・・・思いつかないですごめんなさい。

(`・ω・´)

こうして考えてみると、私がthisを書いてるのは、私のコーディングスタイル(や視力)の関係上、結果的に必要になったからではと思います。
同様に、thisを書かない人にも、その人のコーディングスタイルがあって、結果的に書かないようになったのではないかと。そういう方々と一緒に仕事するようになった時に、ついでに意見を伺ってみたいです。

え、thusっていう変数作りたい?ちょっと表に出ようか(#^ω^)

余談(VSの設定)

ちなみにVSでは不必要なthisを書くと薄く表示してしまいます。「このthis消せ」というメッセージです。VS2017では、この薄く表示するのをやめさせることができます。

メニューの[ツール]→[オプション]→[テキストエディター]→[C#]→[コードスタイル]→[全般]に、thisの優先という項目がありますので、そこで「thisを優先する」に設定すればおkです。ちなみにthisをつけないとエラーにしちゃうぞみたいな設定も可能です。

image.png

2871contribution

そりゃ書いたほうがいいですよ。
書かないとローカル変数なのかメンバ変数なのか分からなくなります。
IDEには分かっても私にはわからんです。

(大仏ってなんだ??)

2142contribution

自分はthisが無くてもローカルかメンバか分からなくなることは今のところ無いのですが、拡張機能入れると色分けできるようです。

https://marketplace.visualstudio.com/items?itemName=AndreasReischuck.SemanticColorizer

Edge1.png

※色やスタイルは指定できます。

ご参考まで。

3884contribution

単に可読性だけの問題ではなく、フィールド名を隠蔽するローカル変数を作ったとき(もしくは削除したとき)後方のコードの意味が変化するのですがそれに気付くきっかけがないという危険性もあります。

むしろthisを省略して良いというC++の言語仕様がどういう経緯で生まれたのか、そしてどういう意図でJava/C#にも受け継がれたのかが気になります。

122contribution

@aosho235 そうですよね!機械には分かるけど人間には分からないことってたくさんありますよね!

@matsuda_sinsuke 大仏ですキリッ

@takabosoft ありがとうございます!これ、VSでもできるんですね!参考になります

@yuba そういう名前の仮引数やローカル変数は作らないようにしてたので逆に気付きませんでした…!だからこそだと思いますが、危険ですね。VSもデフォルトで不要なthisは削除すべきとして薄く表示しますよね。あのデフォルト設定もどこから出たのか気になります。