20220108のC#に関する記事は3件です。

C#で二次元配列(リスト)を扱う

はじめに 先日業務にて表題の件について調べたので共有します。 どうやら C# で多次元リストを宣言するための組み込みメソッドはありません。 だそうです。 本題 ジェネリックコレクションの List クラスを多重入れ子(今回は二重)にすることで実現できます。 List<List<T>> ※ T は任意のデータ型 作成する二次元リスト Id[0] Id[1] Id[2] IdList[0] 0 5 10 IdList[1] 1 6 11 IdList[2] 2 7 12 IdList[3] 3 8 13 IdList[4] 4 9 14 利用例 qiita.cs List<List<int>> IdList = new List<List<int>>(); // 二次元リスト作成 for(int i=0; i<5; i++) { List<int> Id = new List<int>(); Id.Add(i); Id.Add(i+5); Id.Add(i+10); IdList.Add(ID); } // 値の参照 foreach(var ids in IdList) { if(ids[0] % 2 == 0) { Console.Write(ids[1]); } else { Console.Write(ids[2]); } Console.WriteLine(); } ちなみに クラスやタプルのリストでも実現できるみたいです。 クラス qiita.cs public class Id { public int oldId { get; set; } public int newId { get; set; } } List<Id> IdList = new List<Id>(); for(int i=0; i<5; i++) { Id id = new IdList(); id.oldId = i; id.newId = i+5; IdList.Add(id); } タプル qiita.cs List<(int, int)> IdList = new List<(int, int)>(); for(int i=0; i<5; i++) { IdList.Add((i, i+5)); } さいごに 初投稿がニッチな内容となってしまいましたが、アウトプットの習慣づけをしたいと思い投稿しました。 今後もアウトプットの習慣づけ兼備忘録の場として利用していくので、優しく見守っていただけたら嬉しいです。 最後までお読みいただきありがとうございました。 また逢う日まで。 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GitLabで.Net FrameowrkのソフトのCI環境を整える

はじめに 業務上の都合により、Windows Formアプリに関するCI環境を整えることになり、 色々検索していった所GitLabのCI/CDパイプラインである程度どうにかできそうな手がかりを得た。 ただ、色々とかなり複雑に感じたため、忘備録として資料を残しておく 環境 Windows10(Home Editionでも動作可能なはず。) RaspberryPi(GitLab動作用) 大まかな手順 GitLabのセットアップ RaspberryPi上にGitLabをインストールする リポジトリの準備 Windows側のセットアップ Windowsでgitlab-runnerをダウンロードし、インストールする NetCoreバージョンのPowershell(pwsh.exe)をインストールする 何らかの方法で(手段は問わない)pwsh.exeへのパスを通す .NetFrameworkのツールのインストールを行う ビルドツール テストツール Windows上のRunnerをGitLabへ登録する Jobの設定 GitLabのセットアップ これは公式ホームーページのReapberryPi用のインストール手順ページに従うだけだから割愛する。 セットアップが完了したら、CI環境を整えたいレポジトリを作成しておく。 Windows側のセットアップ Runnerのダウンロードとサービスへの登録 下記を参照すれば、とりあえずgitlab-runnerは登録できる。 ただし、自分の場合は何をやっても自分のアカウントでサービスとしてrunnerを立ち上げることができなかった。 ちなみにこの時点で他の設定を整えて動かそうとしたらこのようなエラーが出る。 .NetCore版のPowershell(pwsh)のインストールと環境変数の調整が必要となるようだ。 (※ログが長すぎたので改行しています。) ERROR: Job failed (system failure): prepare environment: failed to start process: exec: "pwsh": executable file not found in %PATH%. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information .NetCore版のPowershellのインストール 最新のPowershellでは.Net Core 6.0が必要になる。.Net Core 6.0も一緒にダウンロードしよう。 Powershellのインストール方法にはいくつか方法があるが、多分msiを使用するのが無難だと思う。 PowerShellのインストールサイト .Net 6.0(Powershellに必要なライブラリ)のダウンロードサイト 自分は「.NET グローバル ツールとしてインストール」からインストールしてしまったため、後でpwsh.exeへのパスを調べてシステムの環境変数に追加する必要が出てしまった。 その他必要なツールのインストール Visual Studio 2019の時点では、.Net FrameworkのアプリのテストにはMSTestを使用するようだ。 その場合は下記記事の「コンソールでUnitTestを実施」以降を参考にすれば良い。 あとは使用した環境に一致したBuild ToolsをAgentsをダウンロードしたサイトからダウンロードしよう。 この記事投稿時点(Visual Studio 2022)の時点では、各ツールへのパスは下記の通り。 (2022以外を使う場合は下記の2022の数字を変更すればよさそうだ。) ビルドツール C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\MSBuild\Current\Bin\MSBuild.exe テストツール C:\Program Files (x86)\Microsoft Visual Studio\2022\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe ビルドはともかく、テストツールはどのように動くのかわかってないから試しに動かしてみる。 下記のようにコマンドを送って試してみた。 $mstest = "C:\Program Files (x86)\Microsoft Visual Studio\2022\TestAgent\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" $testtarget = ".\(テストプロジェクト)\bin\Release\MainTest.dll" cd (ソリューションのディレクトリ) & "$mstest" "$testtarget" 出力結果はこんな感じ。 Microsoft (R) Test Execution Command Line Tool Version 17.0.0 Copyright (c) Microsoft Corporation. All rights reserved. テスト実行を開始しています。お待ちください... 合計 1 個のテスト ファイルが指定されたパターンと一致しました。 成功 TestMethod1 [5 ms] テストの実行に成功しました。 テストの合計数: 1 成功: 1 合計時間: 1.4221 秒 RunnerのGitLabへの登録 これは上の方のリンク「GitLabにWindowsのrunnerを追加する」を参考にすれば問題ないので割愛します。 Jobの設定 まずは動作確認をしたかったので、サンプルに「windows」のタグだけ追加してみた。 (runnnerで指定しているタグを過不足なく入れておく必要があります) .gitlab-ci.yml stages: # List of stages for jobs, and their order of execution - build - test build-job: # This job runs in the build stage, which runs first. stage: build tags: - windows script: - echo "Compiling the code..." - echo "Compile complete." unit-test-job: # This job runs in the test stage. stage: test # It only starts when the job in the build stage completes successfully. tags: - windows script: - echo "Running unit tests... This will take about 60 seconds." - sleep 60 - echo "Code coverage is 90%" このファイルが含まれるコードを実際にPushしたら次のような動作になった。 とりあえず、適当なスクリプトをWindows上で動かせるようになったので、 今後はこの環境を使って実際に色々動かして試してみることにする。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

気ぃつけよ! JavaエンジニアがC#を学ぶ時につまずくポイント3選

こんにちは。 Javaを今まで書いていてここ2ヶ月でC#を書き始めたものです。 それにしてもJavaとC#って似てますよね? 「JavaとC#ってほぼ同じだし、1日で文法さらえたわ」 こんなふうに思っていたら、要注意です(自戒)。 似てるが故にハマる落とし穴というものもあるのです。 背景 聞くところによると、Javaが1995年に最初に登場して、C#が2000年に最初に登場したようです。 Javaの方が5年上の先輩ですね。 よって、C#にできるけどJavaではできない、みたいな言語機能もあるわけです。 まあでもお互いに影響し合って今まで成長してきたのでしょうね。 ここからは、実際にJavaとC#の相違点について考え、Javaエンジニアが特に陥りやすい言語仕様などを紹介していきたいと思います。 1. "protected" の意味が違う JavaをやっていてC#を始めて触る人は大概、「internalってなんだ?でもprotectedは共通してる!たぶん同じ意味だろうな」なんて思ったりするものです。 違います。 JavaとC#では、アクセス修飾子の意味合いはかなり違います。 (privateとpublicしか同じじゃないです) Java protected: 同じパッケージ内 or 継承クラス (修飾子なし): 同じパッケージ内 C# protected internal: 同じアセンブリ内 or 継承クラス internal: 同じアセンブリ内 protected: 継承クラス private protected: 同じアセンブリ内 and 継承クラス このように… 違うんですよね、意外と。 表にまとめてみるとこんな感じです。 アクセスしやすさ Java C# 詳細 1 public public どこでも 2 protected protected internal 同じパッケージ/アセンブリ内 or 継承クラス 3 (修飾子なし) internal 同じパッケージ/アセンブリ内 3 - protected 継承クラス 5 - private protected 同じアセンブリ内 and 継承クラス 6 private private 同じクラス内のみ こうみると、C#はJavaの悪い点をちゃんと改善していて良いなって思いますよね。 C#での「修飾子なし」のアクセスレベル またもう1つC#を学ぶ際に罠になるのが、C#での「修飾子なし」の場合です。 この場合は、アクセスレベルには「規定のアクセシビリティ」が付与されます。 しかしこの「規定のアクセシビリティ」、つまり「デフォルトのやつ」がものによって異なっているんですよね〜。 アクセスされるもの メンバのアクセス修飾子 class private struct private interface public enum public つまりこれらは一緒です。 public class TestClass { private int _privateInt1; int _privateInt2; } public struct TestStruct { private string _privateString1; string _privateString2; } public interface ITest { public void PublicFunction1(); void PublicFunction2(); } 覚え方としては、「考えられるアクセス修飾子の中で、一番厳しいもの」と覚えれば大丈夫です。interfaceやenumはそもそも普通は実装を持つものではないし、privateにする意味もないのでpublicになってる、と考えれば納得がいきます。 2. getHoge, setHogeなどを大量に書きがち Java上がりのエンジニアは、getter関数やsetter関数を大量に書く習性があります。 なぜなら、Javaで大事なメンバをpublicで宣言して…なんて事したら上司にこっ酷く怒られたからです。 なので普通は外部に公開したいメンバには基本的にgetterとsetterを書いて値の正当性を保持したりするのですが… C#erはあんまりSetHogeやGetHogeなんて書きません。代わりに「プロパティ」を使用します。 プロパティとは? getterとsetterが備わっているメンバみたいなもののことをいいます。 例えば以下の例。 Person.cs public class Person { private int _age; public int Age { internal get { return _age; } set { if (value < 0 || 150 < value) throw new System.ArgumentOutOfRangeException(); _age = value; } } } _ageというメンバは外からは見えません。しかしAgeというプロパティを通してそのメンバにアクセスすることができるようになります。 また、getterとsetterにはそれぞれ個別のアクセシビリティを指定することができます。上記の例では、getterはinternal, setterはpublicとなります。これによって歳を気にしだしたアラフォーのおばさんも、外部のアセンブリには自分の歳を非公開にすることができます(まあReflection使ったら見れるんですけどね)。 これによって、下手に冗長なコードを書かずにすみますし、綺麗ですよね。 でもsetHoge, getHogeを書きたくなるのはわかります…僕も抜け出せないでいました… 3. Javaにはない参照渡しがある…!! そうです。Javaにはない参照渡しが存在してしまっているのです。 Javaでは? Javaでは、関数の引数はいわゆる「値渡し」というものでした。正確に言えば、全てが「クラスのインスタンスへのポインタ」でした。なので、新しいnewしたインスタンスを返してあげたい時は絶対に返り値で戻す必要があったのです。 Java初心者じゃなければ以下の意味がわかるはずです。 ListRefModify.java public class ListRefModify { public static void main(String[] args) { ArrayList<String> list = new ArrayList<String>(); list.add("original"); modify(list); System.out.println(list); } private static void modify(ArrayList<String> list) { list = new ArrayList<String>(); list.add("modified"); } } 出力: ["original"] ※なぜならlistはポインタの値であり、ポインタの指し示す値を変えているわけではないから C#では? C#ではJavaでは紛らわしかった、ポインタ渡しではなく、純粋な「参照渡し」ができます! C#では参照渡しのためにref, out, in という3つのキーワードを、実引数と仮引数の両方に使います。 ref ただの参照渡し。 public static void modify(ref int a) { a = 2; } public static void test() { int a = 1; modify(ref a); Console.WriteLine(a); // 2 } in 呼ばれた関数内で、readonlyとして使われる参照渡し。「見るだけ、お触りはだめ」的なノリ。 public static void modify(in int a) { // a = 2; // compile error int b = a; Console.WriteLine(b); // 0 } public static void test() { int a = 0; modify(in a); Console.WriteLine(a); // 0 } out 呼ばれた関数内のみで、絶対に初期化される参照渡し。「これになんかもの入れといて〜」的なノリ。 public static void modify(out int a) { a = 2; } public static void test() { int a; modify(out a); Console.WriteLine(a); // 2 } 問題解決…! これにより、先ほどのJavaの問題(つまり、呼び出し先でnewしたやつを入れてそれを反映させたいという欲求)が解消されます。ListRefModify.javaをC#で書き直してみます。 ListRefModify.cs public class ListRefModify { public static void Main(String[] args) { List<string> list = new List<string>(); list.Add("original"); Modify(ref list); Console.WriteLine(list); } private static void Modify(ref List<string> list) { list = new List<string>(); list.Add("modified"); } } 出力: ["modified"] C#はもともとクラスに関しては参照渡しですが、refをつけることで「参照の参照渡し」ができるようになります。これで、上記のように呼び出し先で違うインスタンスの参照を代入しても値が変更されないことがありません。 最初は多いように感じますが、使っていくたびにC#の参照渡しの多様性のありがたみに気づき、C#無しじゃ生きていけないようになり、そしてJavaが霞んで見えてくるでしょう おわり 今回はJavaに慣れている人が驚くであろう、そしてつまずくであろうポイントを3つ紹介しました。なぜかC#を称賛してJavaを卑下しそうになりましたが、Javaにだって良いところはあります。どっちも愛してあげようね。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む