投稿者: tomato-note

  • [C#]Any関数の中にAny関数がある場合のリファクタリング

    あるリストの中に別のリストの要素が存在するかを確認したい場合、以下のようなコードを書くことができます。

    var flag = list.Any(x => list2.Any(y => y == x));

    しかし、Any関数の中にAny関数が入っており、可読性がかなり悪いです。ぱっと見は何をやっているのか全く分かりません。あと別の記事で書いていますが、かなり遅いです。

    [C#]Any関数の速度 – TOMATONOTE (tomato-note.com)

    今回は備忘録的に修正案を三つ提示します。

    Any の中で Contains を使用する

    Any の中で Contains メソッドを使うことで、より簡潔なコードにできます。O(n)で探索してくれます。

    var flag = list.Any(x => list2.Contains(x));

    Intersect を使用する

    Intersect メソッドを使うことで、両リストの共通要素が存在するかどうかをチェックできます。Any を使って共通要素が1つでもあるか確認します。

    var flag = list.Intersect(list2).Any();

    HashSet を使用して効率化

    ToHashSetの計算量が無視できるくらいlist2 が大きい場合、HashSet を使うことで、Contains 操作を高速化できます。

    var set = list2.ToHashSet();
    var flag = list.Any(x => set.Contains(x));
  • [C#]Any関数の速度

    ChatGPT大先生にとあるAny関数を使ったソースコードを添削していただくと、大体HashSetにしたほうがO(1)だから、こっちの方がいいよと仰います。

    本当なのかいろいろと試してみたいと思います。

    素のままの検索速度の差

    順序がランダムな10000の数字の配列を用意します。その中から0を探すことを1000回行ったときの速度を計測しました。

    Any関数の場合

    var list = Enumerable.Range(0,10000).OrderBy(i=>Guid.NewGuid()).ToArray();
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,1000))
    {
        var flag = list.Any(x => x == 0);
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");
    処理時間:43ms
    処理時間:41ms
    処理時間:41ms
    処理時間:41ms
    処理時間:42ms
    処理時間:17ms
    処理時間:14ms
    処理時間:14ms
    処理時間:13ms
    処理時間:13ms

    HashSetの場合

    var list = Enumerable.Range(0,10000).OrderBy(i=>Guid.NewGuid()).ToArray();
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,1000))
    {
        var hashSet = list.ToHashSet();
        var flag = hashSet.Contains(0);
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");
    処理時間:131ms
    処理時間:121ms
    処理時間:110ms
    処理時間:123ms
    処理時間:169ms
    処理時間:114ms
    処理時間:120ms
    処理時間:153ms
    処理時間:143ms
    処理時間:134ms

    個人的には既に意外ですが、まさかのAny関数の勝利でした。

    毎回ToHashSetする方がパフォーマンスとしては悪いという結果になりました。

    ちなみにToHashSet()をタイマーの外で行うと、さすがO(1) の実行速度です。

    var list = Enumerable.Range(0,10000).OrderBy(i=>Guid.NewGuid()).ToArray();
    var hashSet = list.ToHashSet();
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,1000))
    {
        var flag = hashSet.Contains(0);
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms
    処理時間:0ms

    配列の中に別の配列の要素が含まれるか

    とある大きい配列の中に、別で用意した配列が含まれているかのチェックをよくやることがあり、これをChatGPT先生に聞くと、HashSetを使ったほうが良いという回答をよく貰います。

    文章だと分かりづらいので、例をソースコードで示すと、下記のようになります。

    var list1 = [0,1,2,3,4,5,6,7,8,9];
    var list2 = [2,5];
    // 自分が提案した方法
    var list3 = list1.Where(x => list2.Any(y => x == y));
    
    // ChatGPT先生のリファクタリング結果
    var hashSet = list2.ToHashSet();
    var list4 = list1.Where(x => hashSet.Contains(x));

    実際の実務で使うコードは、オブジェクトの配列となるため、これよりも複雑ですが、大雑把に言えば、このようになります。もちろん配列の大きさ、検索するオブジェクトの位置によって実行速度は大きく変わってきますが、ここでは、大量のオブジェクトの中を検索するという前提で考えていきます。

    Any関数を使う場合

    var list = Enumerable.Range(0,10000).OrderBy(i=>Guid.NewGuid()).ToArray();
    var list2 = Enumerable.Range(0,1000);
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,1000))
    {
        var flag = list.Any(x => list2.Any(y => y == x));
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");
    処理時間:182ms
    処理時間:174ms
    処理時間:172ms
    処理時間:171ms
    処理時間:181ms
    処理時間:176ms
    処理時間:175ms
    処理時間:176ms
    処理時間:181ms
    処理時間:190ms

    Any関数が二つあって一見、何をやってるのか非常に分かりにくいので、出来れば、これは避けたいです。

    HashSetを使う場合

    var list = Enumerable.Range(0,10000).OrderBy(i=>Guid.NewGuid()).ToArray();
    var list2 = Enumerable.Range(0,1000);
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,1000))
    {
        var hash = list2.ToHashSet();
        var flag = list.Any(x => hash.Contains(x));
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");
    処理時間:12ms
    処理時間:7ms
    処理時間:7ms
    処理時間:7ms
    処理時間:7ms
    処理時間:7ms
    処理時間:6ms
    処理時間:6ms
    処理時間:8ms
    処理時間:10ms

    !!

    list2が大きい場合、list2をHashSetにする方が速くなりました。

  • JavaScriptの==と===の違い

    JavaScriptを学ぶときに避けて通れないのが、=====の違いです。これらの演算子はどちらも「等しいかどうか」をチェックするために使いますが、実際にはその動作が大きく異なります。この記事では、=====の違いを明らかにし、それぞれがどのような場合に使用されるべきかを解説します。

    1. ==(抽象等価演算子)

    ==は「抽象等価演算子」とも呼ばれ、2つの値が「等しいかどうか」を比較します。しかし、この演算子は自動的に型変換(Type Coercion)を行います。つまり、比較する値が異なるデータ型であった場合でも、JavaScriptは自動的に型を変換して比較を試みます。

    例えば:

    console.log(5 == "5"); // true

    上記のコードでは、5(数値)と"5"(文字列)が比較されています。==演算子はまず文字列を数値に変換し、その後に比較を行うため、結果はtrueになります。

    2. ===(厳格等価演算子)

    一方で、===は「厳格等価演算子」と呼ばれ、値だけでなくデータ型も同時に比較します。つまり、2つの値が異なるデータ型であった場合、型変換を行わずにfalseを返します。

    例えば:

    console.log(5 === "5"); // false

    こちらでは、数値の5と文字列の"5"が比較されていますが、型が異なるため結果はfalseになります。

    3. =====、どちらを使うべき?

    多くのJavaScript開発者は、型変換による予期しないバグを避けるために===(およびその反対の!==)を使用することを推奨しています。型変換が必要ない限り、===を使用することでより予測可能で安定したコードを書くことができます。

    もちろん、特定のシナリオで型変換が意図された場合、==を使うこともありますが、その場合は注意深く意図を確認し、必要に応じてコメントを残しておくと良いでしょう。

    4. まとめ

    • == は抽象等価演算子で、異なるデータ型間で型変換を行い比較を行う。
    • === は厳格等価演算子で、型変換を行わずに値とデータ型の両方を比較する。

    JavaScriptで予測可能な挙動を実現するためには、===を使用することが推奨されます。特に大型プロジェクトやチーム開発では、型の違いによるバグを防ぐためにも厳格等価演算子をデフォルトとする方が良いでしょう。

    JavaScriptの理解が深まるにつれ、これらの演算子の使い分けができるようになると、より安全で信頼性の高いコードが書けるようになるはずです。

  • [C#, VB.NET] 警告CA1416の意味

    CA1416は、.NETにおけるプラットフォームの互換性に関連する警告メッセージです。この警告は、コードが特定のプラットフォーム(例えば、Windows、Linux、macOSなど)でのみ実行される可能性があることを示しています。

    CA1416 警告の意味

    この警告は、あなたが書いたコードが現在実行中のプラットフォームで動作しない可能性があることを知らせるためのものです。たとえば、Windows固有のAPIを使用しているコードをクロスプラットフォームアプリケーションに含めると、この警告が表示されることがあります。

    対策方法

    条件付きコンパイルディレクティブを使用する

    特定のプラットフォームでのみ実行されるコードを囲むために、条件付きコンパイルディレクティブを使用できます。

    #if WINDOWS
    // Windows固有のコード
    #endif

    プラットフォームのチェック

    実行時にプラットフォームをチェックし、対応するコードを実行することもできます。

    if (OperatingSystem.IsWindows())
    {
        // Windows固有のコード
    }
    else if (OperatingSystem.IsLinux())
    {
        // Linux固有のコード
    }

    プラットフォーム互換性属性を使用する

    特定のプラットフォームでのみ利用可能なAPIを示すために、プラットフォーム互換性属性を使用できます。

    [SupportedOSPlatform("windows")]
    public void WindowsSpecificMethod()
    {
        // Windows固有のコード
    }

    プラットフォーム互換性の確認

    .NET 5以降では、プラットフォーム互換性を確認するための新しいAPIが導入されました。これにより、特定のプラットフォームでのみ使用可能なAPIや機能を明示的に指定できます。これにより、開発者はコードが異なるプラットフォームでどのように動作するかをより正確に制御できます。

    まとめ

    CA1416警告は、クロスプラットフォームアプリケーションの開発者がコードの互換性を確保するために重要な指針となります。この警告を無視せず、適切な対策を講じることで、アプリケーションの信頼性と移植性を向上させることができます。

  • [C#,VB.NET]警告CA2200の意味

    CA2200は、キャッチされた例外を再スローする際にスタックトレース情報が失われることに関する警告です。この警告は、例外をキャッチした後に単純に再スローするのではなく、元の例外情報を保持するための適切な方法を使用するよう促すものです。

    CA2200 警告の意味

    通常、例外がキャッチされた後に再スローされると、例外のスタックトレース情報がリセットされ、新しい例外として扱われます。これにより、元の例外がどこで発生したのかを特定するのが難しくなります。この警告は、この問題を避けるために、元の例外情報を保持したまま再スローする方法を使用することを推奨しています。

    対策方法

    例外をキャッチした後で再スローする際には、次のように単にthrowキーワードを使用します。これにより、元の例外とそのスタックトレース情報が保持されます。

    try
    {
        // 例外を引き起こす可能性のあるコード
    }
    catch (Exception ex)
    {
        // 例外を処理するためのコード
        throw;  // 元の例外を再スロー
    }

    不適切な再スローの例

    以下は、警告CA2200が発生する典型的な例です。ここでは、新しい例外がスローされるため、元の例外情報が失われます。

    try
    {
        // 例外を引き起こす可能性のあるコード
    }
    catch (Exception ex)
    {
        // 例外を処理するためのコード
        throw ex;  // これは元の例外を再スローするのではなく、新しい例外として扱われます
    }

    正しい再スローの方法

    上述の通り、単にthrowを使用することで、元の例外情報を保持したまま再スローできます。

    try
    {
        // 例外を引き起こす可能性のあるコード
    }
    catch (Exception ex)
    {
        // 例外を処理するためのコード
        throw;  // 元の例外を再スロー
    }

    まとめ

    CA2200警告は、例外の再スロー時に元のスタックトレース情報を保持するための適切な方法を使用することを促すものです。例外をキャッチして再スローする際には、必ずthrowキーワードを使用して元の例外情報を保持するようにしましょう。これにより、デバッグや問題のトラブルシューティングが容易になります。

  • うつ病体験談 その1

    20代の最後に発症して、未だに治療中。現在31歳。

    今は安定しているので、このタイミングで思い出として記しておこうと思う。

    ネットで調べると、入院したとか、1日全く動けないみたいな記事が大量に見られるけど、自分はそこまでじゃなかったというのも今回書いておこうと思った理由の一つである。

    とは言いつつ、合計6ヶ月休職しているので、軽症とするのはおかしいのか?とか思ったり。

    見る人が見たら甘えに見えるかもしれないけど、こっちは医者から診断受けてるんだって強気に出てみたり。

    思うところはあるけど、軽症は軽症なりの苦しみがあるっていうことをいろんな人に知ってもらえたら、書いた意味があったかなと思ったり

    あととりあえず思い付いた順に書いているので、あしからず。気が向いたときに書き直そうと思ってます。

    きっかけ

    うつ病は、ストレスが積み重なって、爆発したときに発症するらしい。

    もともと好きなこともあまりないし、ストレス発散が苦手な方と言うのはあったと思う。

    コロナウィルスの流行で心配性な自分の性格も相まって、ストレスが爆発してしまった。

    コロナが流行り始めて1ヶ月くらいのとき、マスク警察に動画を撮られながら、なんでマスクつけてないんですか?と詰められたり(売ってなかったので付けられなかった)

    ちょっと喉が痛いと、ものすごく不安になったり、かと言って独りなので、誰にも相談できなかったり

    在宅勤務100%になって生活習慣が完全に変わったり。もともと出社100%だったので、家賃が安い家に住んでたのだが、バスが家の前を通る音がうるさすぎて、だんだん耐えられなくなってきたり。(あの時、バスに乗っていた人は居たのだろうか)

    毎日ニュースでコロナ関係の悪いニュースが流れてたり。とにかく世の中の雰囲気に飲まれやすいというのが今回分かった

    こんな感じで考え出すとキリがないくらいいろんなきっかけがあったと思う

    症状

    不安になることはよくあることだから、そんなに気にしてなかった

    症状を自覚し始めたのは、朝が辛すぎて、始業時間に間に合わなくなってきた頃だ

    何かがおかしいと思いつつ、そのまま働き続けてた

    ある日の昼頃だったと思う

    日本語のドキュメントが読めなくなった

    何を言ってるのか分からないかもしれないが、文字であることは認識できるのだけど、文章として全く頭に入ってこなくなった

    よく集中できないっていうことがあるけど、それはまだ集中できる状態なのかもしれない。気合いでどうにもならない状態がその先にあるのだ。

    このときの文字が読めない衝撃と人間の脳は文字であることと文章であることを認識することを別々で管理してるんだという感動があったのを覚えてる

    仕事にならなかったので、その日は午後休を取った

    他にも色々あって

    家に食べるものが無いのでコンビニまで歩いて行ったとき、自分が宙に浮いて、自分を見ながら歩いてる感覚になった。

    周りの景色が若干セピア色に見えたりした。

    高い音が聞けなくなって音楽を聞いたりアニメを見たりできなくなった。

    やたら時間が長く感じるようになった。と言っても暇を感じなくなっていた。ベッドで横になって過ぎない時間をただ待っていた。

    すぐ疲れるようになった。

    自分はなんでダメなやつなんだと考えるようになった。

    死んでみたらいいのかなとか考えたりもした。

    仕事も休みがちになり始めた。

    1ヶ月で半分くらいしか仕事ができない状態だった。

    明らかにおかしいと感じて色々調べると、2週間程度憂鬱な気分が晴れない場合、心療内科に行った方がいいと知った

    診断

    電話が嫌すぎてネット予約できる心療内科を探して行った

    うつ病だった

    時間が過ぎなすぎて、色々と調べたため、驚きはなかったけど、まあやっぱりかという落胆はあった。

    仕事ができないので一旦2ヶ月休職した。

    うつ病の薬はお酒がNGになるため、病院に行く前の晩に普段はあまりやらない晩酌をした。

    やっぱりうつ病の薬が処方された。

    最初は、レクサプロが処方されたが、周りがまぶしく見えるという副作用でトリンテリックスに変更になった。周りがまぶしいと主治医に伝えると、嬉しそうにレアケースですね!と言っていたのを覚えている。

    その2へ続く

  • VB初心者向け:SubとFunctionの違いを解説

    Visual Basic (VB) は、シンプルかつパワフルなプログラミング言語で、多くのアプリケーション開発に利用されています。VBでは、手続き(プロシージャ)を定義するために SubFunction という2つのキーワードを使用しますが、これらの違いを理解することは非常に重要です。今回は、VBにおける SubFunction の違いについて詳しく解説します。

    Sub とは?

    Sub は、戻り値を返さないプロシージャ(手続き)を定義するために使用されます。主に操作や処理を実行するために使用され、他のプログラミング言語でいうところの void 関数に相当します。

    特徴:

    • 戻り値を返さない
    • 操作や処理を実行する
    Public Sub DisplayMessage(ByVal message As String)
        MsgBox message
    End Sub

    この例では、DisplayMessage という Sub プロシージャが定義されています。このプロシージャは、引数として渡されたメッセージをメッセージボックスに表示するだけで、戻り値を返しません。

    Function とは?

    Function は、値を返すプロシージャを定義するために使用されます。計算や操作の結果を返す必要がある場合に使用されます。

    特徴:

    • 戻り値を返す
    • 計算や操作の結果を返す
    Public Function AddNumbers(ByVal a As Integer, ByVal b As Integer) As Integer
        AddNumbers = a + b
    End Function

    この例では、AddNumbers という Function プロシージャが定義されています。このプロシージャは、2つの整数を受け取り、その合計を返します。

    Visual Basic (VB) では、Function プロシージャを使用して値を返す場合、その値を返す方法として Return ステートメントまたは関数名を使用することができます。どちらの方法でも値を返すことができますが、Return ステートメントを使用するのが一般的です。

    Return ステートメントを使用する方法

    Return ステートメントを使用することで、Function プロシージャから値を返すことができます。

    Public Function AddNumbers(ByVal a As Integer, ByVal b As Integer) As Integer
        Return a + b
    End Function

    どちらの方法を使用すべきか?

    • Return ステートメント:
      • より明確で可読性が高い
      • 他の多くのプログラミング言語と一貫性がある
    • 関数名に値を代入:
      • VB の古いバージョンからの方法で、一部のプログラマにとっては馴染みがあるかもしれません

    SubFunction の違いをまとめると

    • Sub: 戻り値を返さない。例: メッセージの表示、ファイルの書き込み、ログの記録など。
    • Function: 戻り値を返す。例: 計算結果の取得、データの変換など。

    クラスメソッドとしての SubFunction

    SubFunction は、クラスのメンバーとしても定義できます。ここでは、クラスメソッドとしての SubFunction を紹介します。

    Public Class MathOperations
        ' Subメソッドの定義
        Public Sub DisplayMessage(ByVal message As String)
            MsgBox message
        End Sub
    
        ' Functionメソッドの定義
        Public Function AddNumbers(ByVal a As Integer, ByVal b As Integer) As Integer
            AddNumbers = a + b
        End Function
    End Class

    このクラスでは、DisplayMessage という Sub メソッドと、AddNumbers という Function メソッドが定義されています。

    Public Sub Main()
        Dim mathOps As New MathOperations
    
        ' Subメソッドの呼び出し
        mathOps.DisplayMessage("Hello from the Sub method!")
    
        ' Functionメソッドの呼び出しと結果の取得
        Dim result As Integer
        result = mathOps.AddNumbers(10, 20)
        MsgBox "The result of addition is " & result
    End Sub

    このコードでは、MathOperations クラスのインスタンスを作成し、そのメソッドを呼び出しています。

    静的メソッドとしての SubFunction

    SubFunction は、Shared キーワードを使用して静的メソッドとして定義することもできます。これにより、クラスのインスタンスを作成せずにメソッドを呼び出すことができます。

    Public Class MathOperations
        ' 静的Subメソッドの定義
        Public Shared Sub DisplayMessage(ByVal message As String)
            MsgBox message
        End Sub
    
        ' 静的Functionメソッドの定義
        Public Shared Function AddNumbers(ByVal a As Integer, ByVal b As Integer) As Integer
            AddNumbers = a + b
        End Function
    End Class
    Public Sub Main()
        ' 静的メソッドの呼び出し
        MathOperations.DisplayMessage("Hello from the static Sub method!")
    
        ' 静的Functionメソッドの呼び出しと結果の取得
        Dim result As Integer
        result = MathOperations.AddNumbers(10, 20)
        MsgBox "The result of static addition is " & result
    End Sub

    まとめ

    VBでの SubFunction の違いを理解することは、効果的なプログラムの設計と開発に欠かせません。Sub は戻り値を返さないプロシージャであり、Function は戻り値を返すプロシージャです。これらの使い分けをしっかりと理解し、適切に使用することで、より明確でメンテナンスしやすいコードを作成することができます。

    今後もプログラミングに関する疑問や質問があれば、ぜひコメントで教えてくださいね!

  • [C#]拡張メソッドの使い所

    拡張メソッドは、C#で既存のクラスに新しいメソッドを追加するための強力なツールです。この記事では、拡張メソッドの作り方、メリット、デメリットについて詳しく解説します。

    拡張メソッドの作り方

    自作クラスに拡張メソッドを追加

    まず、自作のクラスに拡張メソッドを追加する方法を見てみましょう。以下に、MyClass というクラスに対して拡張メソッドを追加する例を示します。

    public class MyClass
    {
        public int Value { get; set; }
    }
    
    public static class MyClassExtensions
    {
        public static void PrintValue(this MyClass myClass)
        {
            Console.WriteLine(myClass.Value);
        }
    
        public static void AddToValue(this MyClass myClass, int addValue)
        {
            myClass.Value += addValue;
        }
    }

    拡張メソッドは静的クラスを定義することで作成可能です。このクラスの中にメソッドを定義します。メソッドの第一引数にthis MyClass myClassを入れることでMyClassの拡張メソッドを定義できます。引数をつけたい場合は、第二引数を定義することで引数ありの拡張メソッドを定義できます。

    MyClassExtensionsは、任意の名前に出来ますが、可読性の観点から「〇〇Extensions」とすることをおすすめします。

    この拡張メソッドを使用することで、MyClass のインスタンスで PrintValue メソッドを呼び出すことができます。

    MyClass instance = new MyClass { Value = 42 };
    instance.PrintValue();  // 出力: 42
    instance.AddValue(10); // 52

    標準ライブラリのクラスに拡張メソッドを追加

    次に、標準ライブラリのクラスに対して拡張メソッドを追加する方法を見てみましょう。自作クラスに普通にメソッドを定義すれば良いので拡張メソッドを定義することは、あまりないと思います。拡張メソッドは、標準ライブラリのクラスなどに自作のメソッドを追加したい場合によく利用されます。以下に、string クラスに対して拡張メソッドを追加する例を示します。

    public static class StringExtensions
    {
        public static bool IsNullOrEmpty(this string str)
        {
            return string.IsNullOrEmpty(str);
        }
    }

    この拡張メソッドを使用することで、string のインスタンスで IsNullOrEmpty メソッドを呼び出すことができます。

    string myString = null;
    bool result = myString.IsNullOrEmpty();  // true

    拡張メソッドのメリット

    継承をしなくても、クラスにメソッドを追加できる

    拡張メソッドの最大のメリットは、既存のクラスに対して継承を使わずにメソッドを追加できることです。これにより、クラスの継承階層をシンプルに保つことができます。標準ライブラリにメソッドを追加したいために継承を利用して、新しい親クラスを定義すると可読性、保守性が低下します。

    利用箇所での可読性の向上

    拡張メソッドを使うことで、メソッドチェーンを作成したり、自然な文脈でメソッドを呼び出すことができます。これにより、コードの可読性が向上し、直感的に理解しやすくなります。

    if (myString.IsNullOrEmpty())
    {
        // 何かの処理
    }

    拡張メソッドのデメリット

    プロジェクトに新規加入した開発者にとっては可読性が低下

    拡張メソッドは、その存在を知っている開発者にとっては便利ですが、新しくプロジェクトに参加した開発者にとっては、どのクラスがどのメソッドを持っているのかが分かりにくくなる可能性があります。実装されているクラスも静的クラスで、名前も「〇〇Extensions」です。これにより、コードの理解が難しくなることがあります。

    まとめ

    拡張メソッドは、既存のクラスに対して新しいメソッドを追加するための便利なツールですが、その使用には注意が必要です。適切に利用することで、コードの再利用性や可読性を向上させることができますが、過度な使用はプロジェクトの可読性を損なう可能性があります。拡張メソッドの利点と欠点を理解し、バランスの取れた方法で利用することが重要です。

    最近まで知らなかったのですが、Enum型にも拡張メソッドを定義できます。これに関しては、可読性を上げることができてかなりいいと感じています。

  • [C#]ランダムな配列の作り方

    検証用として考えました。(実務では、無意味ですね)

    ある配列があって中身をランダムな配列にするやり方をまとめます。

    Guidを利用する方法

    var randomList = list.OrderBy(i=>Guid.NewGuid()).ToArray();

    Guidは、生成のたびに異なる値を出してくれます。これを利用して、Guidの順に並び替えることで任意の配列をランダムな順序に変更できます。

    例えば、数値のランダムな順序の配列なら

    var list = Enumerable.Range(0,10);
    var randomList = list.OrderBy(i=>Guid.NewGuid()).ToArray();
    foreach(var i in randomList)
    {
        Console.WriteLine(i);
    }

    このようにすれば、0~9までの間のランダムな配列が簡単に手に入ります。

    またlistを文字列の配列にすれば、ランダムな順序の文字列の配列も作ることができます。

    var list = new List<string>{"apple", "banana", "hogehoge","hugahuga", "orange"};
    var randomList = list.OrderBy(i=>Guid.NewGuid()).ToArray();
    foreach(var i in randomList)
    {
        Console.WriteLine(i);
    }

    次回は、これを使って検証したいことがあったので、それについて書いていきます!

  • [C#]実行時間計測

    polyglotで実行時間を計測したいと思って、調べました。

    Stopwatchクラスを使えば、簡単に計測できます。

    using System.Diagnostics;
    
    var stopwatch = Stopwatch.StartNew();
    foreach(var i in Enumerable.Range(0,10))
    {
        // 何らかの処理
        await Task.Delay(1000);
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");

    StartNew()は、静的メソッドでStopwatchクラスのインスタンスを作成後、すぐにStopwatchをスタートします。

    もちろん下記で書いても同じ動作です。

    using System.Diagnostics;
    
    var stopwatch = new Stopwatch()
    stopwatch.Start();
    foreach(var i in Enumerable.Range(0,10))
    {
        // 何らかの処理
        await Task.Delay(1000);
    }
    stopwatch.Stop();
    Console.WriteLine($"処理時間:{stopwatch.ElapsedMilliseconds}ms");