私がJavaよりC#をおすすめする理由

2015年1月21日に投稿 → に更新 技術

「Javaのコードって冗長でごちゃごちゃしてて嫌だなぁ…、でもPHPとかRubyみたいな動的型言語だとなんか不安…。」

私は10年間Javaを使った後、PHP、Ruby、Node.js等の動的型言語を使いました。動的型言語の簡潔さに魅了され大ファンになりました。

その結果、Javaをディスるようになってしまったのですが(笑)、動的型言語にも不満がないわけではありません。

IDEによる入力補完やシンボルの検索機能などは静的型言語の方が手厚いですし、静的型言語であればコンパイル時に発見されるようなコーディングミスが動的型言語では実行しないと見つからないというデメリットもあります。

なので、

「静的型言語で動的型言語みたく簡潔に書ける言語があればいいのになぁ…」

と思っていたら、 そんな言語があったんです。

C#です!

「えっ? C#ってJavaをマネしただけでしょ?」って?そんなことありません。

C#は静的型言語の良さを持ちながら動的型言語のような簡潔さを持つ素晴らしい言語なんです。その魅力の一端を紹介します。

Javaのアクセサ地獄を解決するC#のプロパティ

Javaにはフィールド(インスタンス変数)をクラス外から設定参照するアクセサメソッドという概念があります。 get~、set~というお決まりのコードです。

public class UserInfo {
    private String email;
    private String password;
    
    public void getEmail() {
        return email;
    }
    public void setEmail(String s) {
        email = s;
    }
    public void getPassword() {
        return password;
    }
    public void setPassword(String s) {
        password = s;
    }
}

//使用例
UserInfo user = new UserInfo();
user.setEmail("foo@bar.com");
String email = user.getEmail();

「だったらフィールドをpublicにすりゃいいじゃん」とおもうのですが、Javaの設計慣習では「publicにしてしまうと、後でそのフィールドにアクセス制限をかけることができないのでアクセサメソッド経由でフィールドにアクセスする設計がよい」とされています。

例えば、後になってpasswordに値をセットするロジックに文字列長が8未満だったらエラーにしたいとなった場合に以下のように対処できるという発想です。

    public void setPassword(String s) {
        if (s.length < 8)
            throw new PasswordSetException(s);
        password = s;
    }

まぁ、滅多にこんなことをすることはないでしょうけど、確かにアクセサメソッドを挟んでおくことで値の参照設定にロジックをはさむ柔軟性が生まれます。

ですが、そのためにいちいちアクセサメソッドを書くのは面倒です。

IDEによるアクセサコードの自動生成ができるので書く手間はある程度減らせますが、コードが冗長になる問題は残ります。 C#にはこれを解決するプロパティという機能があります。

public class UserInfo {
    private String email;
    private String password;
    public String Email { get { return email;} set { email = value }}
    public String Password { get { return password;} set { password = value }}
}

//使用例
UserInfo user = new UserInfo();
user.Email = "foo@bar.com";
String email = user.Email;

さらに短い書き方もできます。

public class UserInfo {
    public String Email { get; set;}
    public String Password { get; set; }
}

プロパティが良いのはpublicフィールドの参照とプロパティ参照の記法が同じなので初めpublicフィールドで定義しておいて後で必要になったらプロパティに変えることができます。

publicフィールドからプロパティに変更しても呼び出し側の記法は同じなので変更する必要はありません。

public class UserInfo {
    public String email;
    public String password;
}
//使用例
UserInfo user = new UserInfo();
user.email = "foo@bar.com";
String email = user.email;

//後で変更
public class UserInfo {
    //プロパティは頭が大文字じゃなくてもいい、大文字にしてるのはただの慣例
    public String email { get; set;}
    public String password {
        get { return password;}
        set { 
            if (value.length < 8)
                throw new PasswordSetException(value);
                password = value;
            }
        }
    }
}
//使用例(publicフィールドの時と同じ記法が使える)
UserInfo user = new UserInfo();
user.email = "foo@bar.com";
String email = user.email;

JavaのHashMapを連想配列のような記法で扱えるC#のDictionary

JavaのHashMapはデータの追加、取得をメソッドで行いますが、C#のDictionaryはLL言語が連想配列を扱うような記法で追加、取得ができます。

・JavaのHashMapコード

HashMap<String, String> map = new HashMap<String, String>();
map.put("foo@bar.com", "pass1");
map.put("hoge@moge.com", "pass2");
String password = map.get("foo@bar.com");

・C#のDictionaryコード

// C#はvarキーワードによる型推論ができるので型を省略できるのもナイス!
var map = new Dictionary<String, String>();
map["foo@bar.com"] = "pass1";
map["hoge@moge.com"] = "pass2";
String password = map["foo@bar.com"];

断然C#の方がすっきりしているし直観的にわかりやすいですね!

JavaのListを配列のような記法で扱えるC#のインデクサ

Javaには可変長配列を実装したArrayListというクラスがあります。これまたデータの追加、取得をメソッドで行います

ArrayList list = new ArrayList();
list.add("foo@bar.com");
list.add("hoge@moge.com");
list.get(0); //foo@bar.comが返る
list.get(1); //hoge@moge.comが返る

C#にはインデクサという配列の記法を使ったアクセス方法があります。

var list = new List();
list.Add("foo@bar.com");
list.Add("hoge@moge.com");
// 配列と同じ記法で参照できる(インデクサ)
list[0]; //foo@bar.comが返る
list[1]; //hoge@moge.comが返る

C#だとRubyやJavaScriptに近い簡潔なコードが書けます!それでいて静的型チェックがなされる、スバラシー!!

Javaより9年早いクロージャ(Delegate)の導入

Javaは2014年にJava8でようやくクロージャが導入されました。

一方、C#にはVisual Studio 2005で搭載されたC#2.0の時点で、Javaのクロージャに相当するDelegateという機能がありました。

例としてListの中からemailがfoo@bar.comのデータを探すコードを書いてみます。 Java7までの書き方(いわゆるforおじさんの書き方)

ArrayList users = new ArrayList
users.add(...); // データを何件か追加したとする
UserInfo foundData = null;
for (int i = 0; i < user.size(); i++) {
    UserInfo user = users.get(i);
    if (user.getEmail().equals("foo@bar.com")
        foundData = user;
}

C#だと同じ処理をDelegate(ラムダ式)を使って簡潔に書けます。

var users = new List
users.Add(...); // データを何件か追加したとする
UserInfo foundData = users.Find(user => user.Email == "foo@bar.com");

Javaは2014年にクロージャが導入されてようやく、C#と同じような書き方ができるようになりましたが、C#に比べて9年間もの間forおじさんをしなければならなかったわけです。

どの言語を使うかでプログラミングのトレンドについていきやすさが変わるってことです。

ですから、先進的な機能を次々と取り入れているC#の方が断然おすすめなんです!

おまけ: 給料で損した経験談

私と同じ失敗をされないよう経験をシェアしてます。

私が新卒で入った会社は社員数80名の零細ベンダーでした。

基本給は17万円で手取りは14万円くらいでした。仕事は客先常駐の業務システム開発(言語はJava)でした。

会社の先輩に「うちの会社って給料安すぎませんか?」って聞いてみたところ、

「どこもそんなもんだよ、ふつうふつう」

と言われて、「そうなのかなぁ…」と半信半疑ながら4年半勤めて年収は320万円でした…。

「やっぱ安すぎだろ!?」と思って試しに転職してみたら、

仕事内容はほぼ同じで年収が120万円もアップしたんです!

「こんなことがあっていいのか…」って感じですが、現実はどんな仕事をするかより、どの会社で働くかで給料が決まる面が大きいんですよね。

給料の高さが全てではありませんが、年収相場より大幅に安いという方は一度転職を検討してみると良いと思います。

相場がどれくらいか分からないという方は私のこれまでの年収推移を、ぜひ参考にしてみて下さい。