挨拶を返すアプリを作ってみたをやり直した

# はじめに
2017年頃にC#...というよりVisual Studioプログラミングのリハビリ目的で「挨拶を返すアプリ」を作ってみた...という記事でわからないまま放置してたところがあったので書き直し。

## 当時やりたかったこと
+ HelloApp.exeを引数なしで指定すると何も表示しない
+ HelloApp.exeに引を入れて実行すると「Hello. {引数に入れた名前}さん!」と表示する。

# プロジェクト概要

| 1 | 2 |
|:-:|:-:|
| プロジェクト テンプレート | コンソールアプリ(.NET Framework) |
| プロジェクト名 | HelloApp |
| フレームワーク | .NET Framework 4.7.2 |

# 最初の試行

## プログラムの挙動
+ helloman.exeを実行すると「Hello.太郎さん!」と挨拶する。
+ 引数で名前を指定すると「太郎」が「指定した名前」に代わって、挨拶する。

## 間違ったコード
```csharp:program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Halloman
{
    class Program
    {
        static void Main(string[] args)
        {
            string yourname;
            if (args.Length > 0) //引数が指定されていればyournameに代入
            {
                yourname = args[0];
            }
            Hello(yourname);
        }

        // 挨拶を表示する処理
        private static void Hello(string name)
        {
            Console.WriteLine("Hello. {0}さん!", name);
        }
    }
}
```

## つまづいたところ
Visual Studioからビルドエラーが出力。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/c9c83d89-6365-fd6a-11e4-683c626c10fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/1a62134b-6136-7b6d-921b-abd1a310540f.png)

未割当のローカル変数 yournameを処理できないよと言われたので、ビルド処理 = コンパイルをするための条件が整ってないんだなと誤解したまま、とりあえず未割当変数をなんとかすりゃいいかなとテキトーに進めてしまった。。

## 頂いたアドバイス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184939/5d474884-79e7-4862-3390-a33c04cbb411.png)


悩んでるところ(足りない知識)はそこじゃないよとアドバイスを頂くが、当時いろいろと限界を超えていた為「ふーんなるほど(よくわからん)」状態。
テキトー修正を施し、エラー回避して無理やり動くものにしてしまった。

## テキトー修正

```csharp:
static void Main(string[] args)
{
  string yourname = "太郎";
  if (args.Length > 0) //引数が指定されていればyournameに代入
    {
      yourname = args[0];
    }
  Hello(yourname);
}
```

まぁ未割当変数のエラーが回避できるようになったのでデバッグビルド処理は進んだ。


# やりおなし

## プログラムの挙動を考え直した。
引数を指定していない場合、複数引数を指定していた場合などのケースが全然作られていなかったので処理を追加。

+ HelloApp.exeを引数なしで指定すると何も表示しない
+ HelloApp.exeに引数を1つ指定して実行すると「Hello. {引数に入れた名前}さん!」と表示する。
+ HelloApp.exeに複数の引数を指定して実行すると「Hello. {引数に入れた名前}さん!」を引数で指定した数の分だけ表示する。



## 1回目の改修

突っ込みどころはあるが、改修途中のテンポラリも記載しているため、ここについてはスルーして頂けるとありがたい。

```csharp:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelloApp
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                ReturnError("挨拶する相手の名前がわかりません。");
            }

            if (args.Length > 0)
            {
                string yourname;
                for (int ti=0; ti<args.Length; ti++)
                {
                    yourname = args[ti];
                    SayHello(yourname);
                }
            }

        }

        // 挨拶を表示する処理
        private static void SayHello(string name)
        {
            Console.WriteLine("Hello. {0}さん!", name);
        }

        private static void ReturnError(string message)
        {
            Console.WriteLine(message);
        }
    }
}
```

## 2回目の改修
どうにも無駄が多いので処理の考え方を変えてみた。

```csharp:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HelloApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 挨拶を返す処理はMainに書かずに関数に書くようにした
            if (args.Length == 0)
            {
                Console.WriteLine("挨拶する相手の名前がわかりません。");
            } else
            {
                SayHello();
            }
        }

        // 挨拶を表示する処理
        private static void SayHello()
        {
            string[] yourname = System.Environment.GetCommandLineArgs();

            for (int ti = 1; ti < yourname.Length; ti++)
            {
                Console.WriteLine("Hello. {0}さん!", yourname[ti]);
            }
        }
    }
}
```

# まとめ
今思い返すと反省点多いなぁ・

- 挙動のパターンに漏れがないか？
- 関数化するならそれなりに処理をまとめよう

# お詫び
また、やり直す前の記事をうっかり更新してしまったのでスクショを持ち越す形にさせていただきました。
gentaroさんごめんなさい。

# 参考
- コマンドライン引数(C#プログラミングガイド) https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/main-and-command-args/command-line-arguments
- Environment.GetCommandLineArgs メソッド https://docs.microsoft.com/ja-jp/dotnet/api/system.environment.getcommandlineargs?view=netcore-3.1