C#

2024年3月10日 (日)

[C#]リストに要素を追加する

Addメソッドは最後に要素を追加する。Insertメソッドは指定のインデックス(0~)の箇所に要素を追加する。

using System;
using System.Collections.Generic;
List names = new List();
names.Add("ライスシャワー");
foreach (string s in names) {
Console.WriteLine($"A: {s}");
}
names.Add("メイショウドトウ");
names.Add("サクラチヨノオー");
foreach (string s in names) {
Console.WriteLine($"B: {s}");
}
names.Insert(1, "スーパークリーク");
foreach (string s in names) {
Console.WriteLine($"C: {s}");
}

実行結果

A: ライスシャワー
B: ライスシャワー
B: メイショウドトウ
B: サクラチヨノオー
C: ライスシャワー
C: スーパークリーク
C: メイショウドトウ
C: サクラチヨノオー

2024年3月 9日 (土)

[C#]リストを作成する

Listクラスを使う。あらかじめusing命令でSystem.Collections.Generic名前空間を指定しておくと便利。

using System;
using System.Collections.Generic;
List names = new List();
names.Add("ライスシャワー");
names.Add("メイショウドトウ");
names.Add("サクラチヨノオー");
foreach (string s in names) {
Console.WriteLine(s);
}

実行結果

ライスシャワー
メイショウドトウ
サクラチヨノオー

2024年3月 8日 (金)

[C#]エラー「CS8370 機能 'target-typed オブジェクトの作成' は C# 7.3 では使用できません。9.0 以上の言語バージョンをお使いください。」

Visual Studio 2022でプロジェクトを読み込んでコンパイルなどをした際に、このようなエラーメッセージが表示されることがある。例えば、以下のような一文を入力すると、赤波線が表示されてエラーが発生していることがわかる。

List<string> memo = new();

これはプロジェクトの言語バージョンが適切に指定されていない。プロジェクトファイルに最新バージョンを使うように指定すればよい。

ソリューションエクスプローラーのプロジェクト名のところで右クリックして、コンテキストメニューの「プロジェクトのアンロード」をクリック。プロジェクト名の最後に「(アンロード済み)」が表示される。

プロジェクト名をダブルクリックする。プロジェクトファイルが表示される。

以下の3行を追加する。PropertyGroupがあるだろうが、そこに2行目だけ含めてもかまわない。

<PropertyGroup>
<LangVersion>latest</LangVersion>
</PropertyGroup>

プロジェクトファイルを保存する。

プロジェクト名のところで右クリックして、コンテキストメニューの「プロジェクトの再読込」をクリック。プロジェクト名の最後の「(アンロード済み)」が消える。

これで、最新の構文が使えるようになる。

2024年3月 7日 (木)

[C#]StreamWriterクラスを使用して文字コードを指定してファイルに書き込む

第3引数にEncodingクラスのGetEncoding メソッドを使用してコードページを指定する。以下は四通りの方法でそれぞれ文字列をファイルに書き出した例。

OutVar.cs

using System.IO;
using System.Text;
using (var sw = new StreamWriter("result/out_default.txt", false)) {
sw.WriteLine("メイショウドトウ役の和多田美咲さん");
}
Encoding enc;
enc = Encoding.GetEncoding("shift_jis");
using (var sw = new StreamWriter("result/out_sjis.txt", false, enc)) {
sw.WriteLine("メイショウドトウ役の和多田美咲さん");
}
enc = Encoding.GetEncoding("utf-8");
using (var sw = new StreamWriter("result/out_utf8.txt", false, enc)) {
sw.WriteLine("メイショウドトウ役の和多田美咲さん");
}
enc = new UTF8Encoding();
using (var sw = new StreamWriter("result/out_utf8encoding.txt", false, enc)) {
sw.WriteLine("メイショウドトウ役の和多田美咲さん");
}

実行してみる。

>OutVar.exe
>type result\out_sjis.txt
メイショウドトウ役の和多田美咲さん
>certutil -encodehex -f out_default.txt dump.txt 10 > nul && type dump.txt
0000 e3 83 a1 e3 82 a4 e3 82 b7 e3 83 a7 e3 82 a6 e3
0010 83 89 e3 83 88 e3 82 a6 e5 bd b9 e3 81 ae e5 92
0020 8c e5 a4 9a e7 94 b0 e7 be 8e e5 92 b2 e3 81 95
0030 e3 82 93 0d 0a
>certutil -encodehex -f out_sjis.txt dump.txt 10 > nul && type dump.txt
0000 83 81 83 43 83 56 83 87 83 45 83 68 83 67 83 45
0010 96 f0 82 cc 98 61 91 bd 93 63 94 fc 8d e7 82 b3
0020 82 f1 0d 0a
>certutil -encodehex -f out_utf8.txt dump.txt 10 > nul && type dump.txt
0000 ef bb bf e3 83 a1 e3 82 a4 e3 82 b7 e3 83 a7 e3
0010 82 a6 e3 83 89 e3 83 88 e3 82 a6 e5 bd b9 e3 81
0020 ae e5 92 8c e5 a4 9a e7 94 b0 e7 be 8e e5 92 b2
0030 e3 81 95 e3 82 93 0d 0a
>certutil -encodehex -f out_utf8encoding.txt dump.txt 10 > nul && type dump.txt
0000 e3 83 a1 e3 82 a4 e3 82 b7 e3 83 a7 e3 82 a6 e3
0010 83 89 e3 83 88 e3 82 a6 e5 bd b9 e3 81 ae e5 92
0020 8c e5 a4 9a e7 94 b0 e7 be 8e e5 92 b2 e3 81 95
0030 e3 82 93 0d 0a

以上より、StreamWriterクラスの第3引数の指定と書き出されるファイルの文字コードの関係は、以下であることがわかる。

文字コードを未指定 → UTF-8(BOM付き)
Shift_JIS → Shift_JIS
UTF-8 → UTF-8(BOM無し)
UTF8Encodingクラスをそのまま指定 → UTF-8(BOM付き)

2024年3月 5日 (火)

[C#]コードページ識別子の一覧を得る

コードページとはWindowsにおいて文字符号化方式を判別するためのもので、特定の文字符号化方式を表すものとしてコードページ識別子(Code Page Identifiers)というのものを割り当てて定義している。それの一覧を表示する方法。

SamplesEncoding.cs

using System;
using System.Text;
Console.Write("CodePage Identifier and Name BrDisp BrSave ");
Console.WriteLine("MNDisp MNSave 1-Byte ReadOnly");
foreach(EncodingInfo ei in Encoding.GetEncodings()) {
Encoding e = ei.GetEncoding();
Console.Write("{0,-6} {1,-25} ", ei.CodePage, ei.Name);
Console.Write("{0,-7} {1,-7} ", e.IsBrowserDisplay, e.IsBrowserSave);
Console.Write("{0,-7} {1,-7} ", e.IsMailNewsDisplay, e.IsMailNewsSave);
Console.WriteLine("{0,-7} {1,-7}", e.IsSingleByte, e.IsReadOnly);
}

動作させてみる。

>SamplesEncoding.exe
CodePage Identifier and Name BrDisp BrSave MNDisp MNSave 1-Byte ReadOnly
37 IBM037 False False False False True True
(表示省略)
65000 utf-7 False False True True False True
65001 utf-8 True True True True False True
>SamplesEncoding.exe | findstr /i "jis utf jp"
932 shift_jis True True True True False True
1200 utf-16 False True False False False True
1201 utf-16BE False False False False False True
12000 utf-32 False False False False False True
12001 utf-32BE False False False False False True
20932 EUC-JP False False False False False True
50220 iso-2022-jp False False True True False True
50221 csISO2022JP False True True True False True
50222 iso-2022-jp False False False False False True
51932 euc-jp True True True True False True
65000 utf-7 False False True True False True
65001 utf-8 True True True True False True

コードページ識別子の詳細については、以下のページを参照のこと。
https://learn.microsoft.com/en-us/dotnet/api/system.text.encoding.getencodings?view=net-8.0#system-text-encoding-getencodings

2024年3月 4日 (月)

[C#]日本語を含む文字列の表示幅をバイト単位で指定する

C#では、内部の文字処理ではUnicodeを使用されているため、シフトJISでいうところの1バイト文字("A"や"1")と2バイト文字("A"や"あ")はいずれも一文字として扱われる。そのため、コマンドプロンプトでの画面表示などで表示位置を揃えようとすると、うまくいかないことがある。以下は、2つの文字列をそれぞれ8文字幅で左寄せで表示した例。

> string s1, s2;
> s1 = "Kaname"; s2 = "カナメ";
> Console.WriteLine("|" + $"{s1, -8}" + "|");
|Kaname |
> Console.WriteLine("|" + $"{s2, -8}" + "|");
|カナメ |

1バイト文字は一文字幅、2バイト文字は二文字幅で表示させたい場合は、その文字列をシフトJISに変換してGetByteCountメソッドで文字のバイト数を調べ、その分を考慮した長さの文字列を作成して表示させればよい。

> Encoding enc = Encoding.GetEncoding("Shift_JIS");
> string s1p, s2p;
> s1p = s1.PadRight(8 - (enc.GetByteCount(s1) - s1.Length));
> s2p = s2.PadRight(8 - (enc.GetByteCount(s2) - s2.Length));
> Console.WriteLine("|" + s1p + "|");
|Kaname |
> Console.WriteLine("|" + s2p + "|");
|カナメ |

2024年3月 2日 (土)

[C#]文字列を正規表現で置換する

RegexクラスのReplaceメソッドを使う。以下は、文字列をファイル名と想定してすべての拡張子(ピリオドを含むピリオドの右側の文字列)を削除した例。

> using System.Text.RegularExpressions;
> string s = "abc.def";
> Console.WriteLine(Regex.Replace(s, "\\..+$", ""));
abc
> string s = "abc.def.ghi";
> Console.WriteLine(Regex.Replace(s, "\\..+$", ""));
abc

2024年2月29日 (木)

[C#]カレントディレクトリを得る、設定する

設定をするには、DirectoryクラスのSetCurrentDirectoryメソッドか、EnvironmentクラスのCurrentDirectoryプロパティに代入する。得るには、DirectoryクラスのGetCurrentDirectoryメソッドか、EnvironmentクラスのCurrentDirectoryプロパティを参照する。

> System.IO.Directory.SetCurrentDirectory(@"C:\Windows\System32");
> Console.WriteLine(System.IO.Directory.GetCurrentDirectory());
C:\Windows\System32
> System.Environment.CurrentDirectory = @"C:\Windows";
> Console.WriteLine(System.Environment.CurrentDirectory);
C:\Windows

2024年2月14日 (水)

[C#]コマンドラインでコンパイルするときのソースファイルの文字コードの指定

-codepageオプションを使う。以下の2行からなるソースファイルをそれぞれWriteLineSjis.cs(文字コードはShift_JISにする)、WriteLineUtf8.cs(同UTF-8)と保存をして、それぞれコードページ識別子である932(Shift_JISのこと)と65001(UTF-8のこと)を指定してコンパイルおよび実行してみる。

using System;
Console.WriteLine("メイショウドトウ役の和多田美咲さんかわいい");

Shift_JISで保存をしたファイルをコンパイルして実行する。

>csc -codepage:932 WriteLineSjis.cs
Microsoft (R) Visual C# Compiler バージョン 4.4.0-6.22608.27 (af1e46ad)
Copyright (C) Microsoft Corporation. All rights reserved.
>WriteLineSjis.exe
メイショウドトウ役の和多田美咲さんかわいい
>csc -codepage:65001 WriteLineSjis.cs
Microsoft (R) Visual C# Compiler バージョン 4.4.0-6.22608.27 (af1e46ad)
Copyright (C) Microsoft Corporation. All rights reserved.
>WriteLineSjis.exe
???C?V???E?h?g?E???a???c???炳??????

UTF-8で保存をしたファイルをコンパイルして実行する。

>csc -codepage:65001 WriteLineUtf8.cs
Microsoft (R) Visual C# Compiler バージョン 4.4.0-6.22608.27 (af1e46ad)
Copyright (C) Microsoft Corporation. All rights reserved.
>WriteLineUtf8.exe
メイショウドトウ役の和多田美咲さんかわいい
>csc -codepage:932 WriteLineUtf8.cs
Microsoft (R) Visual C# Compiler バージョン 4.4.0-6.22608.27 (af1e46ad)
Copyright (C) Microsoft Corporation. All rights reserved.
>WriteLineUtf8.exe
繝。繧、繧キ繝ァ繧ヲ繝峨ヨ繧ヲ蠖ケ縺ョ蜥悟、夂伐鄒主調縺輔s縺九o縺・>

オプションに指定したコードページとソースコードの文字コードが合っていなくてもコンパイルはできるが、文字コードは指定どおりに解釈されてコンパイルされてしまうことに注意。

コードページ識別子の一覧は以下を参照のこと。
https://learn.microsoft.com/ja-jp/windows/win32/intl/code-page-identifiers

2023年10月26日 (木)

[C#]文字列が指定の正規表現とマッチするか否か調べる

System.Text.RegularExpressions名前空間のRegex.IsMatchメソッドを使う。第1引数に検索対象の文字列を、第2引数に正規表現を指定する。マッチすれば(指定した正引き表現に一致する箇所が見つかれば)trueを返し、そうではない場合はfalseが返される。

> using System.Text.RegularExpressions;
> Regex.IsMatch("ABC", "A")
true
> Regex.IsMatch("ABC", "ABCD")
false
> Regex.IsMatch("ABC", "^A")
true
> Regex.IsMatch("ABC", "A$")
false
> Regex.IsMatch("\t", "^\s+$")
(1,23): error CS1009: 認識できないエスケープ シーケンスです
> Regex.IsMatch("\t", "^\\s+$")
true
> Regex.IsMatch("\t", @"^\s+$")
true
> Regex.IsMatch("\t\t", @"^\s+$")
true
> Regex.IsMatch(" ", @"^\s+$")
true
> Regex.IsMatch(" AB ", @"^\s+$")
false

より以前の記事一覧