19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C言語の知識に囚われたC#コードを改善する 第一弾

Last updated at Posted at 2018-05-05

きっかけ

最近読んだコードが クソ 伸び代だらけで、 ムシャクシャていた 仏の気持ちになったので書きました。

C言語の知識しかない状態で C# を書くと大勢の人が似たようなコードに行き着いてしまうと思います。

そこで、どう書くと C# らしくなるのかを自分なりにまとめていきます。

関連記事一覧

第一弾(本記事)
第二弾

直したいポイント

命名規則

命名規則はプロジェクトで定められたものに従うのが勿論ですが、言語としての推奨があるので意識してほしいですよね。
名前付けのガイドライン - Microsoft Docs

Qiita にも記事がありました。
C# CODING GUIDELINES @Ted-HM

特に気になってしまうのは以下の2点でしょう。

// スネークケースは推奨されていない。
public const int HOGE_HOGE = 1;

// ハンガリアン記法も過去のもの。
public int iHoge { get; set; }
public string strHoge { get; set; }

特に命名規則において .NET のクラスライブラリは最大のお手本ですので、自身が書いたコードと見比べてみるのがいいと思います。
(VisualStudio でクラス等にカーソルをあわせて、F12 を押しましょう!)

配列の呪縛 その1

public void Fuga(string[] args)
{
  for (int i = 0; i < args.Length; i++)
  {
    // args[i] に何か処理。
  }
}

このコードは間違いではないですが、以下のデメリットがあります。

  • インデックサ args[i] の部分は些細なミスで例外を引き起こす。
  • 引数が配列型に固定されている。

なので、このように変更します。

public void Hoge(IEnumerable<string> args)
{
  foreach (var item in args)
  {
    // item に何か処理。
  }
}

このコードでは、 for -> foreach の変更以外に、引数の型が IEnumerable<string> に変化しました。

単なる foreach で済むメソッドであれば、この様な引数を定義するのがベストです。
そうすると、以下の様に1つのメソッドで様々な型の引数を受け取れる汎用性が獲得できるのです!

// どれもエラーにならない!
Hoge(new string[] { });
Hoge(new List<string>());
Hoge(new Collection<string>());

これにはインターフェイスが関連しているのですが、ここを理解できれば C# のレベルがグッと上がります。
(欲を言えば Linq を扱えるまでレベルアップしてほしい。)

配列の呪縛 その2

メソッドの戻り値やプロパティ等でも配列を使いがちです。
そして、こんなコードを書いてしまいます。

public string[] Fuga()
{
  var list = new List<string>();
  // あれこれ list.Add() する処理
  return list.ToArray();
}

前述の呪縛 その1 で引数が配列になっているため、それに合わせる為だというのが理由の一つだと思います。

しかし、それがすでに解決済みならば List<string> を直接 return でき、 ToArray() による無駄なオブジェクトの生成を減らすことができます。

さらに戻り値の型を IReadOnlyList<string> や IEnumerable<string> に変える事で、メソッドの外で Add() 等の変更が不可能になり、意図しないミスを防ぐ事ができます。

public IReadOnlyList<string> Fuga()
{
  var list = new List<string>();
  // あれこれ list.Add() する処理
  return list;
}
var fuga = Fuga();

// 読み出しはできる
foreach (var item in fuga) { }
var tmp = fuga[0];

// 書き込みはできない
// コンパイルエラー
fuga.Add("");
fuga[0] = "";

おまけ

foreach 可能で readonly なインターフェイスを以下にまとめました。
用途に合わせて必要十分なインターフェイスを選定してください。
(もちろんすべて配列と互換があります。)

インターフェイス名 foreach サイズ (int Count(){get;}) インデックサ (T this[int]{get;})
IEnumerable<T> × ×
IReadOnlyCollection<T> ×
IReadOnlyList<T>
19
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?