はじめに

 C#の入門曞を䞀通り読み終えたのに、どうにもモダモダが残る――そんな経隓はありたせんか。この連茉では、C#の぀たずきやすい抂念を、生成AIChatGPTやGeminiなどずの察話を通じお攻略しおいきたす。
 ポむントは、AIに「教えおもらう」姿勢です。わからないこずを玠盎にぶ぀け、深掘りし、コヌドを曞かせ、怜蚌する。この流れを身に぀ければ、どんな抂念でもAIを䜿っお自力で孊べるようになりたす。
 第1回のテヌマは「if文地獄」。if文地獄がなぜよくないのか、改善する手段はどういうものか、AIを䜿っお攻略しおいきたす。

たずはコヌドを芋せお「䜕が問題」ず聞く

 孊習の出発点は、「このコヌド、䜕かたずい気がする」ずいう違和感です。
 あなたは、コンビニのレゞシステムを開発しおいたす。最初はクレゞットカヌドだけ察応すればよかったのですが、電子マネヌやQRコヌド決枈も、ず芁望が増えおきたした。急いで察応したコヌドがこちらです。

public void ProcessPayment(string paymentType, decimal amount)
{
    if (paymentType == "CreditCard")
    {
        Console.WriteLine($"クレゞットカヌドで {amount}円 を決枈したした");
    }
    else if (paymentType == "ElectronicMoney")
    {
        Console.WriteLine($"電子マネヌで {amount}円 を決枈したした");
    }
    else if (paymentType == "QRCode")
    {
        Console.WriteLine($"QRコヌド決枈で {amount}円 を決枈したした");
    }
}

 玠盎なコヌドですが、このたた決枈手段が増え続けたらどうなるでしょう
 5皮類、10皮類ず増えおいくず、メ゜ッドが肥倧する気がしたす。この違和感を、AIにぶ぀けおみたしょう。

AIに問題点を聞く

 次のプロンプトに続けお、先ほどのコヌドをそのたた入力しおみたす。その際、単に「問題点を教えお」ず聞くず、倚くの事柄が列挙され、どれが重芁なのか芋えづらくなりがちです。回答が広がりすぎたずきは、数を絞ったりひず぀だけ教えお、芳点を指定したり保守する立堎で困るこずはするず効果的です。  ここでは最初から、もっずも問題になりそうなこずず限定しお聞いおみたす。

次のC#コヌドを芋おください。今は3皮類の決枈手段ですが、今埌5皮類、10皮類ず増えおいく予定です。もっずも問題になりそうなこずをひず぀教えおください。
さきほどのコヌドをそのたた入力

 こうするず、もっずも重芁で本質的な回答が返っおきたしたChatGPTでの回答䟋です。

もっずも問題になりそうなのは 「決枈手段を远加するたびに、このメ゜ッドを毎回線集しないずいけなくなる倉曎に匱い」 こずです。

支払い手段が 5→10→
 ず増えるほど if / else if が䌞びおいき、修正箇所が垞にここに集䞭したす。
その結果、远加のたびに 既存の分岐を壊す挏れが出るテスト範囲が広がる ずいう圢で事故りやすくなりたす以䞋、略

 AIは、決枈手段を远加するたびに、このメ゜ッドを毎回線集しないずいけなくなるこずが、もっずも問題だず指摘しおくれたした。これが、いわゆる「if文地獄」の正䜓です。
 では、どう盎せばよいのでしょうか。さきほどの回答に、解決法が含たれおいるかもしれたせんが、あらためお聞いおみたす。

解決策を聞く

 回答がむやみに広がらないよう、指摘された問題に絞っお、解決策を聞いおみたしょう。

「決枈手段を远加するたびに、このメ゜ッドを毎回線集しないずいけなくなる」ずいう問題を解決するために、もっずもよい方法を教えおください。

 ChatGPTでは、次のような回答でした。

いちばん筋がいいのは StrategyパタヌンDIで「決枈手段ごずの凊理」をクラスに分離し、呌び出し偎は"遞ぶだけ"にする方法です。
こうするず 新しい決枈手段を远加しおも既存のProcessPaymentは基本的に觊らないで枈みたすOCP: 開攟/閉鎖原則。

䟋むンタヌフェヌス実装クラスレゞストリ
以䞋、コヌド䟋や「もっずもよい」理由が続く

 Geminiでも䌌たような内容で、むンタヌフェヌスによる「ストラテゞヌパタヌンStrategy Patternの導入」を提案しおくれたした。ただ、正盎ピンず来たせん。もう少し深掘りしおみたしょう。

「もっずわかりやすく」ず深掘りする

 技術甚語が出おきお理解が止たったら、たずえ話や図解を求めるのが効果的です。

たずえ話を求める

 抜象的な抂念を、身近な物にたずえおもらいたす。

ストラテゞヌパタヌンがよくわかりたせん。身近な物にたずえお説明しおもらえたすか

 Geminiでは、次のような回答でした回答内容は、適宜芁玄しおいたす。

・「USB Type-C ポヌト」にたずえる
PC偎は、挿されたものが䜕であるか詳しく知らなくおも、「USB芏栌むンタヌフェヌスに沿っおいる」ずいうこずさえ分かれば、通信を     開始できたす。
ストラテゞヌパタヌンずは、「共通の接続口むンタヌフェヌス」を䜜っおおき、䞭身具䜓的な凊理を埌から「プラグむン」のように付け替え可胜にする仕組みのこずです。

 他にも、電源コンセントや決枈端末など、いく぀かのたずえを提案しおくれたした。最初のコヌドがたさに決枈システムの話なので、もっずも身近な「決枈端末」のたずえで図解を䜜っおもらいたしょう。

図解を䟝頌する

 今回は、高品質の図解が埗られる、Gemini 3 Pro ImageNano Banana Proを䜿いたした。Geminiのモデルで、「思考モヌド」か「Pro」を遞択し、次のようなプロンプトを詊しおみたす。

コンビニの「決枈端末」のたずえを䜿っお、ストラテゞヌパタヌンの抂念を説明する図解をシンプルなむラストで䜜成しおください。
  • Geminiの初回生成むメヌゞ|

    Geminiの初回生成むメヌゞ

 決枈端末ず耇数の決枈手段が描かれたした。もちろんこれは䞀䟋で、AIはさたざたな図解を䜜成しおくれるはずです。今回の図解だず、どれがむンタヌフェヌスで、どれがクラスなのか、察応関係がわかりにくいですね。

䞍明点を確認する

 もう少し具䜓的に指瀺しおみたしょう。次のように聞いおみたす。

この図で、「むンタヌフェヌス」は具䜓的にどの郚分に察応しおいたすか その郚分をもっず匷調しおもらえたすか
  • 修正埌のGeminiの生成むメヌゞ

    修正埌のGeminiの生成むメヌゞ

 AIは「共通の差蟌口がむンタヌフェヌスに察応する」ず説明し、その郚分を匷調した図を生成しおくれたした。これで「むンタヌフェヌス共通の差蟌口」ずいうむメヌゞが぀かめたした。

「増えたらどうなる」ず聞く

 最初の問題は、「決枈手段が増えるたびに修正が必芁」でした。では、このたずえではどうなるのでしょうか

新しく「顔認蚌決枈」が远加されたら、この図はどう倉わりたすか
  • 顔認蚌決枈を远加したGeminiの生成むメヌゞ

    顔認蚌決枈を远加したGeminiの生成むメヌゞ

 図を芋るず、顔認蚌決枈が远加されおも、端末偎はたったく倉わっおいたせん。新しい決枈手段は、共通の差蟌口に合う圢で接続されただけ。これがむンタヌフェヌスの匷みです。この、図解で拡匵性を確認するステップは、埌ほどコヌドでも怜蚌したす。  図解でむメヌゞが぀かめたした。次は、これをコヌドで確認しおみたしょう。

「コヌドで曞くずどうなる」ずAIに生成させる

 図解で理解できたら、次はコヌドを考えおみたしょう。これたでの回答にコヌドが含たれおいるかもしれたせんが、あらためおAIに䟝頌しおみたす。

コヌドを生成させる

 ここでもAIは、拡匵性や安党性などを考慮したコヌドを䜜成する堎合がありたす。それはそれで有甚なものですが、より本質的なこずを理解するために、最小限のコヌドで、ずいった指瀺を加えたす。
 先ほどの、もっずもよい方法を聞いた埌なら、次のようになるでしょう。

その、もっずもよい方法を甚いお、最初の問題コヌドを改善しおください。最小限のコヌドでお願いしたす。

 図解を生成した埌なら、「図をコヌドにするならどうなりたすか最初の問題コヌドを」ずいうプロンプトでもいいでしょう。
 AIは次のようなコヌドを生成しおくれたした実際の出力は異なる堎合がありたす。

// 共通のむンタヌフェヌス図の「共通の接続口」
// 「この Pay機胜 さえ持っおいれば、どんなカヌドでも受け付けたす」ずいうルヌル
public interface IPayment
{
    void Pay(decimal amount);
}

// 各決枈手段むンタヌフェヌスを実装するクラス
public class CreditCard : IPayment
{
    public void Pay(decimal amount) => Console.WriteLine($"クレゞットカヌドで {amount}円 を決枈したした");
}

public class ElectronicMoney : IPayment
{
    public void Pay(decimal amount) => Console.WriteLine($"電子マネヌで {amount}円 を決枈したした");
}

public class QRCode : IPayment
{
    public void Pay(decimal amount) => Console.WriteLine($"QRコヌドで {amount}円 を決枈したした");
}

// 決枈端末改善されたクラス
// 以前のような if (paymentType == "CreditCard") ... ずいう分岐は消滅したした。
public class ShopSystem
{
    public void ProcessPayment(IPayment paymentCard, decimal amount)
    {
        // 端末は、差し蟌たれたカヌドのボタンを抌すだけ
        // 䞭身がクレカなのかQRなのかは気にしたせん。
        paymentCard.Pay(amount);
    }
}

class Program
{
    static void Main()
    {
        ShopSystem terminal = new ShopSystem();

        // クレカを䜿いたいなら、クレカを䜜っお枡す差し蟌む
        IPayment myCard = new CreditCard();
        terminal.ProcessPayment(myCard, 1000);

        // QRを䜿いたいなら、QRを䜜っお枡す差し蟌む
        IPayment myPhone = new QRCode();
        terminal.ProcessPayment(myPhone, 500);
    }
}

 実行するず、次のように出力されたす。

クレゞットカヌドで 1000円 を決枈したした
QRコヌドで 500円 を決枈したした

 ShopSystemクラスは、枡された決枈手段がクレゞットカヌドなのかQRコヌドなのかを知りたせん。それでも、IPaymentむンタヌフェヌスのPayメ゜ッドを呌ぶだけで、正しい凊理が実行されたす。
 コヌドの構造を敎理しおおきたしょう。たず、IPaymentむンタヌフェヌスが「共通の差蟌口」に圓たりたす。Payメ゜ッドを持぀こずだけを定矩しおおり、実装メ゜ッドの䞭身はありたせん。
 CreditCard、ElectronicMoney、QRCodeの各クラスが、この差蟌口に合う「各決枈手段」です。それぞれが、: IPaymentず曞くこずでIPaymentを実装し、Payメ゜ッドの䞭身を具䜓的に曞いおいたす。「=>」は、1行で枈むメ゜ッドの省略蚘法です䞭括匧で曞いおも同じ。
 ShopSystemクラスが「決枈端末」です。匕数の型をIPaymentむンタヌフェヌスにしおいるため、具䜓的な決枈手段を知らなくおも、Payメ゜ッドを呌び出すだけで決枈できたす。

コヌドの意味を確認する

 コヌドは生成されたしたが、なぜこれで問題が解決するのか、確認しおおきたしょう。

このコヌドで、最初の問題決枈手段が増えるたびに修正が必芁がどう解決されたのか、説明しおください。

 AIの説明を芁玄するず、次のような内容でした。

  1. 「条件分岐if文」が消滅した
  2. 具䜓的な凊理が「倖」に出た
  3. 「倉曎」ではなく「远加」で察応できるようになった
 最初のコヌドでは、ProcessPaymentメ゜ッドの䞭に、すべおの決枈手段の凊理が詰め蟌たれおいたした。改善埌は、各決枈手段の凊理がそれぞれのクラスに分離され、ShopSystemクラスはIPaymentむンタヌフェヌスだけを盞手にしおいたす。先ほどの図解ず同じこずを、コヌドで衚珟できおいたすね。

顔認蚌決枈を远加しお怜蚌する

 図解のずきず同様に、本圓に修正䞍芁か、コヌドでも詊しおみたしょう。

顔認蚌決枈を远加するコヌドを曞いおください。

 この回答では、次のようなクラスを远加するだけ、ずいう回答になりたした。

// 顔認蚌決枈を远加新しいクラスを䜜るだけ
public class FaceAuthPayment : IPayment
{
    public void Pay(decimal amount) => Console.WriteLine($"顔認蚌で {amount}円 を決枈したした");
}

 新しいクラスを1぀䜜るだけで、ShopSystemクラスには䞀切手を加えおいたせん。䜿うずきは、Mainメ゜ッドに次のように曞くだけです。

IPayment myFace = new FaceAuthPayment();
terminal.ProcessPayment(myFace, 2000);

 最初のif文地獄ず比べおみたしょう。

  • 改善前決枈手段を远加するたびに、ProcessPaymentメ゜ッドを線集する既存コヌドに手を入れる
  • 改善埌新しいクラスを远加するだけ既存コヌドには觊れない
 既存コヌドの倉曎が必芁だったのが、新しいコヌドの远加になりたした。觊るコヌドの範囲がたったく違いたすね。

「本圓に解決した」ず疑問をぶ぀ける

 ここで1぀疑問が浮かびたした。AIに聞いおみたす。

でも結局、どのIPayment実装クラスを䜿うか遞ぶずきに、if文が必芁になりたせんか 本圓にこれで問題は解決したのでしょうか

 AIは、次のような蚀葉から回答を返しおきたした。

そのツッコミ、かなり栞心です。結論から蚀うず、
「if文分岐をれロにする」のが目的じゃなくお、「分岐を“増えない堎所”に閉じ蟌める」のが目的です。
以䞋、説明が続く

 回答が長いので、「回答を抜粋する圢で、芁玄しお」ず指瀺するず、次のような回答でした。

・分岐は「れロにする」のが目的ではなく、増えない堎所に閉じ蟌めるのが目的。
・元コヌドは決枈手段远加のたびに ProcessPayment を線集し、if/else が肥倧化しお壊れやすい。
・远加時にやるのは 新クラス远加 + 登録蚭定。既存の重芁ロゞックを觊らずに枈むので安党でテストもしやすい。
・「問題が解決した」ずは、倉曎箇所を局所化しお、远加が既存コヌド改造にならない状態にできた、ずいう意味。

 AIは、if文は残るが、倉曎の圱響範囲が限定されるず説明しおくれたした。  確かに、ナヌザヌの遞択に応じおどのクラスを生成するかを決める郚分には、䜕らかの分岐が残りたす。しかし、重芁なのは、決枈凊理の本䜓であるShopSystemクラスからif文が消えたこずです。if文をれロにするこずが目的ではなく、倉曎箇所を局所化しお倉曎に匷い蚭蚈にするこずが目的ずいうわけです。

「誰が遞ぶの」ずさらに深掘りする  もう1぀疑問が出おきたした。

ShopSystemクラスは具䜓的な決枈クラスを知らないずのこずですが、では、どの決枈クラスを䜿うかは誰が決めるのですか

 AIは、倖郚から泚入するずいう考え方を説明しおくれたした。

決めるのはShopSystemではなく、倖偎の「構成担圓」です。
具䜓的には、よくある遞び方は3぀ありたす。
1) DIコンテナが決めるいちばん倚い
2) 蚭定ファむルappsettings等が決める
3) Factory工堎圹が決める
以䞋、具䜓的な説明が続く

 先ほどのコヌドでも、Mainメ゜ッドの䞭でIPaymentの実装クラスを生成し、ShopSystemのProcessPaymentメ゜ッドに枡しおいたした。これがたさに、倖郚から泚入する圢です。この考え方を発展させたものが、「䟝存性泚入DI」ず呌ばれる蚭蚈パタヌンです。興味がある方は、さらに深掘りしおみおください。

䟝存性泚入が分かるように、先ほどの決枈端末の図解を倉曎しおもらえたすか
  • 䟝存性泚入の芖点を远加したGeminiの生成むメヌゞ

    䟝存性泚入の芖点を远加したGeminiの生成むメヌゞ

 たた、䟝存性泚入を䜿ったコヌド䟋を䜜成しおもらうのもいいでしょう。  このように、1぀の疑問から次の抂念ぞず自然に぀ながっおいきたす。今回孊んだ、質問→深掘りの流れで、どんどん理解を広げおいっおください。

さらに孊びたい方ぞ

 今回はif文地獄の解決策ずしお、むンタヌフェヌスを䜿ったストラテゞヌパタヌンを孊びたした。その先のテヌマに぀いおも、AIず察話しおみたしょう。本文で觊れた「䟝存性泚入DI」は、誰が決枈クラスを遞ぶのか、ずいう疑問を突き詰めた先にある蚭蚈パタヌンです。たた、むンタヌフェヌスず䌌たしくみに「抜象クラス」がありたす。どちらも共通の型を定矩する点は同じですが、䜿いどころが異なりたす。  たずえば、抜象クラスずの違いは、次のように聞いおみおください。

C#のむンタヌフェヌスず抜象クラスの違いを教えおください。今回の決枈システムの䟋では、どちらを䜿うべきですか

AIず察話するずきのコツ

 今回の孊習をふりかえりながら、察話のコツを敎理しおみたしょう。

STEP1違和感をぶ぀ける

 「このコヌド、䜕が問題」ず聞く。回答が広がりすぎたずきは、数を絞るひず぀だけ教えお、芳点を指定する保守する立堎で困るこずは、構造化させる重芁床順に3぀、䞀蚀ず぀ずいった工倫が有効です。

STEP2解決策を聞く

 「どう盎せばいい」ず聞く。STEP1ず同様、遞択肢が倚すぎるずきは、もっずもよい方法を1぀ず絞るず迷わない。知らない抂念が出おきおも、たずは受け止める。

STEP3わからなければ深掘りする

 「もっずわかりやすく」「身近な物にたずえお」「図で説明しお」ず聞く。

STEP4コヌドに萜ずす

 「コヌドで曞くずどうなる」ず聞く。孊習段階では、最小限のコヌド、もっずもシンプルなコヌドで、などず添えるず、本質ず関係ない芁玠が省かれ、理解しやすくなる。

STEP5怜蚌する

 「本圓にこれで解決する」「なぜ」ず聞く。生成されたコヌドは実際に動かしお確認する。

補足AIの回答を鵜呑みにしない

 AIの回答は垞に正しいずは限りたせん。動䜜するコヌドであっおも、業務のプロゞェクトで掚奚されるスタむルず異なる堎合もありたす。「本圓にこれで正しいですか」「他の曞き方はありたすか」ず聞き返すこずも倧切です。

おわりに

 今回は、AIずの察話を通じお、if文地獄の解決策ずしおむンタヌフェヌスを䜿ったストラテゞヌパタヌンを孊びたした。「質問→深掘り→コヌド生成→怜蚌」の流れは、どんな抂念を孊ぶずきにも䜿えたす。ぜひ、ご自身でAIず察話しながら詊しおみおください。次回は、async/awaitを取り䞊げたす。画面が固たる問題を、AIずの察話で解消しおいきたしょう。

WINGSプロゞェクト 髙江 賢著山田祥寛監修
有限䌚瀟 WINGSプロゞェクトが運営する、テクニカル執筆コミュニティ代衚山田祥寛。䞻にWeb開発分野の曞籍蚘事執筆、翻蚳、講挔等を幅広く手がける。珟圚も執筆メンバヌを募集䞭。興味のある方は、どしどし応募頂きたい。著曞、蚘事倚数。
RSS
X:@WingsPro_info公匏、@WingsPro_info/wingsメンバヌリスト
Facebook

著者に぀いお
パ゜コン黎明期からプログラミングの進化を远い、Web・モバむル・IoT・AIたで倚様な開発珟堎を駆け抜ける。
珟圚、株匏䌚瀟気象工孊研究所で気象×ITの最前線に立ち぀぀、執筆コミュニティ『WINGSプロゞェクト』のメンバヌずしお掻動䞭。