【ワレコの講座】C# プログラミングメモ – トラブル時のチェック項目など

この記事は約13分で読めます。
スポンサーリンク

ワテの場合、いろんなプログラミング言語を使っていると混乱して訳分からなくなる事がある。

些細な事で良くつまづくので気になったことを記録しておく。

以下、自分用のメモ

スポンサーリンク
ワテ推薦のプログラミングスクールで学ぶ
スポンサーリンク
スポンサーリンク

C# プログラミングメモ – トラブル時のチェック項目など

型 ‘System.TypeInitializationException’ のハンドルされていない例外が発生(解決)

2016/8/14

C#で平仮名をローマ字に変換する必要が有ったので、即席でヘンテコな辞書を作って対処した。

static Dictionary<string, string> Kana2RomanDic = new Dictionary<string, string>()
{
    {"あ","a" },{"い","i" },{"う","u" },{"え","e" },{"お","o" },  
    {"か","ka"},{"き","ki"},{"く","ku"},{"け","ke"},{"こ","ko"},
    {"さ","sa"},{"し","si"},{"す","su"},{"せ","se"},{"そ","so"},
    {"た","ta"},{"ち","ti"},{"つ","tu"},{"て","te"},{"と","to"},
    {"な","na"},{"に","ni"},{"ぬ","nu"},{"ね","ne"},{"の","no"},
    {"は","ha"},{"ひ","hi"},{"ふ","fu"},{"へ","he"},{"ほ","ho"},
    {"ま","ma"},{"み","mi"},{"む","mu"},{"め","me"},{"も","mo"},
    {"や","ya"},{" "," "},{"ゆ","yu"},{" "," "},{"よ","yo"},
    {"ら","ra"},{"り","ri"},{"る","ru"},{"れ","re"},{"ろ","ro"},
    {"わ","wa"},{"を","wo"}
};

実行時に、下記エラーが発生する。

型 ‘System.TypeInitializationException’ のハンドルされていない例外が発生しました

追加情報:’TestClass’ のタイプ初期化子が例外をスローしました。

ん?

ああ、解決。急いで作ったので、Dictionaryの要素にこんなのが二ヶ所も残っていた。

{" "," "}

この要素自体は文法的には問題はないが、二ヶ所にあるので同一のキー” ”を登録しようとして例外発生。

これらの不要な要素を削除して解決。

 

なお、C#で平仮名、カタカナ、ローマ字などの相互変換には、

Microsoft Visual Studio International Feature Pack 2.0

と言うのがある。ワテは使った事はないが。

今度試してみるかな。

C#をやるならこの本を一冊読みこなせば完璧だ。

でも、ワテにはハードルが高過ぎるかも。

複数ProjectのSolutionでアセンブリ参照が見つからないエラー(解決)

2016/8/8

症状

以前に作成した複数のC#プロジェクトからなるソリューションがあった。

  • ConsoleApp  コンソールアプリ
  • MyCSharpLib  自作のライブラリ
  • OtherLib1   オープンソースなライブラリ
  • OtherLib2   オープンソースなライブラリ

こういうごく普通のソリューションだ。

プロジェクトの依存関係は、ConsoleAppが他の三つのライブラリを使う設定になっていて、参照設定も正しく行っている。過去にビルドして正常動作していたプロジェクトだ。

久しぶりにConsoleAppをビルドしたら、

エラー 16 型または名前空間名 ‘Category’ が見つかりませんでした。using ディレクティブまたはアセンブリ参照が不足しています。

 

こういうエラーが多数出た。おかしい。

こういう場合、闇雲に参照設定を削除して再設定するなどはやらないのが良い。

過去に正常動作していた訳なので、参照設定などの問題ではないのだ。

しかし、多くの人はやらなくても良い作業をやってしまってますます泥沼に嵌まる。ワテも。

解決

原因はとても簡単だった。ビルドの設定が、

  • ConsoleApp  4.5.2
  • MyCSharpLib  4.5
  • OtherLib1   4.5.2
  • OtherLib2   4.5.2

となっていたのだ。

その理由は、自作のMyCSharpLibライブラリはこのソリューションだけでなく、他のソリューションでも利用していてその時に .NET Framework のバージョンを4.5に変更してビルドしたのだ。

それに気づかずに本ソリューションをビルドしたので上記のように他は4.5.2だが一つだけ4.5になっていた。その結果、今回のエラーが多発したのだ。

対策としては、全て 4.5.2 にしたら解決。

なお今回のようなエラーは、この例のように一つでも .NET Framework のバージョンが異なるプロジェクトが混じっていると必ずしも起こると言う訳ではない。

どういう場合に、こんなエラーが出るのかは未確認。

いずれにしても、過去に正常動作していたソリューションのビルドでエラーする場合には、闇雲に修正するのではなく、プロジェクトのプロパティを確認するのが良いだろう。

 

ワテの場合、10個くらいのプロジェクトのビルドがエラー無く一気に成功するとある種の快感がある。ちょっと変人かも。

このヘンテコな器具で頭を擦ると未体験の快感がある。

おお、スッキリ。

一体全体どんな現場なのか、それが気になる。

?? 演算子(null 合体演算子)

2016/7/17

foreachで配列やリストがnullの場合に NullRefException が throw される。

例えばこういう場合だ。

int[] array = null;

foreach (int i in array)
{
   Console.WriteLine("{0}", i);
}
Console.WriteLine("次の行に来た");

配列arrayがnullなので、foreachでループせずにスキップして次の行を実行して欲しいのだが、実際にはforeachの行でarrayを評価して要素を取り出そうとする処理でNull参照の例外が出る。

う~ん、面倒な奴だ。ヌルならスキップしてくれる方が有り難いのだが。

それにこの場面でNull参照の例外を出して欲しい人も少ないと思う。

 

で、解決方法としては事前にif文や三項演算子でNull判定を行えば良いのだが、以下のような記述でも良い事を発見。

int[] array = null;

foreach (int i in array ?? new int[0])
{
   Console.WriteLine("{0}", i);
}
Console.WriteLine("次の行に来た");

?? って一体何やねん?

クエスチョンマークが二個なので検索してもヒットしない。

“??” c#

でGoogle検索したら、5番目くらいに出てきた。

?? 演算子 (C# リファレンス)

?? 演算子は、null 合体演算子と呼ばれる。

左側のオペランドが null 値でない場合には左側のオペランドを返す。

左側のオペランドが null 値である場合には右側のオペランドを返す。

引用元 https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/operators/null-coalescing-operator

と言う事らしい。

ちなみに、もしarrayがList<int>の場合なら

foreach (int i in array ?? new List<int>() )

かな。

 

また、VB.NETならこんな感じかなと思うが実行はしていない。

Dim array As Integer() = Nothing

For Each i As Integer In If(array, New Integer(-1) {})
   Console.WriteLine("{0}", i)
Next
Console.WriteLine("次の行に来た")

と言うのは、このページ

http://converter.telerik.com/

のサービスを利用してC#からVB.NETへ変換したコードなので。

でもたぶん正しいと思う。VB.NETやC#は.NET Frameworkの技術で作られているので簡単に双方向に変換できるのだ。

null関連の情報として、null許容型と言うのがある。

null 許容型 (C# プログラミング ガイド)

https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/nullable-types/index

こちらはクエスチョンマークが一個だ。

ますます検索しづらい。

ワテもこのnull許容型をだいぶ以前に覚えたが、滅多に使わないので存在を忘れていた。

 

こんな使い方が出来る。

int? x = null;

xに整数だけでなくnullを代入できるのだ。

いつ誰がそんなのを使うのかなと言うと、上記のMSDNプログラミングガイドのページを引用すると、

たとえば、Nullable<Int32> (“Int32 の Nullable” と読みます) には、-2147483648 から 2147483647 の任意の値、または null 値を割り当てることができます。

Nullable<bool> には、true、false、または null の値を割り当てることができます。

数値型と Boolean 型に null を割り当てる機能が便利なのは、値を割り当てられていない可能性がある要素を含むデータベースや他のデータ型を処理するときです。

たとえば、データベースの Boolean フィールドには、値 true または false を格納するか、未定義にすることが可能です。

と言う事だ。

最近、MySQLやSQL Server2014でDB操作をやっているのでこれを使うと便利だ。

JavaScriptなどでは変数に数字でもnullでも代入できるので、そういう感じで使えるのだな。

なお、C#の場合にはstring型はもともとnull許容型なので、?を付けなくてもnullは代入出来る。もし?を付けてしまうと

string? str = null;    // 文法エラー

とすると、

型 ‘string’ は、ジェネリック型のパラメーター ‘T’、またはメソッド ‘System.Nullable<T>’ として使用するために、Null 非許容の値型でなければなりません

と言うエラーが出る。

 

皆さんもどうぞ。

ワテだったら、一冊目はこういう本で勉強するなあ。

Debug.WriteLine で書式設定が効かない

2015/11/06

症状

Debug.WriteLine で、書式に {0} を使ってもうまく行かない。そのまま “{0}” と言う文字列が出力される。

Console.WriteLine なら普通に出来るのに。

string str = “データ”;

Console.WriteLine(“文字列={0}”, str);

みたいに使うのだ。ちなみに Console.WriteLineは C/C++ で言うと、

printf(“%sn”, str);

みたいな感じかな。それをコンソールウインドウに出力するのではなくて、Visual Studioの デバッグ出力に書くのが Debug.WriteLine だ。Debug.Writeというのもある。改行しないバージョンだ。

解決

ググッたら理由や解決方法発見。

Why does Debug.WriteLine incorrectly format strings?

http://stackoverflow.com/questions/22819117/why-does-debug-writeline-incorrectly-format-strings

 

この質問者の人は、私と同じく、

Debug.WriteLine(“Metadata Version: {0}”, version); // version is a string
とやったら

2.0: Metadata Version: {0}

となってしまったようだ。

で、この人は、こんな方法をやったようだ。ワテもやりそうになった。
WriteLine(string.Format(“Metadata Version: {0}”, version));

確かにこれで行けるが、最初の方法でうまく行かない理由が知りたい。そうすると↑のリンク先に理由は書いてあるが英文なので良く分からん。兎に角、以下のような何通りかのやり方があるらしい。

なので、実際に試してみた。

Visual Studio 2013 でC#のコンソールプロジェクトを作って、実験。.NET4.5.2を使った。

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string version = "2.0";
            Debug.WriteLine("1 Metadata Version: {0}", version); // update: version is a string
            Console.WriteLine("2 Metadata Version: {0}", version);
            Debug.WriteLine(string.Format("3 Metadata Version: {0}", version));
            Debug.WriteLine("4 Metadata Version: {0}", version, "");
            Debug.WriteLine("5 Metadata Version: {0}", (object)version);
            Debug.WriteLine("6 Metadata Version: {0}", new[] { version });
            Debug.WriteLine("7 Metadata Version: {0}", version, null);
        }
    }
}
// 実行結果 
// Console出力
// 2 Metadata Version: 2.0
//
// デバッグ出力
// 1 2.0: Metadata Version: {0}     <= 今問題になっている出力
// 3 Metadata Version: 2.0
// 4 Metadata Version: 2.0
// 5 Metadata Version: 2.0
// 6 Metadata Version: 2.0
// 7 Metadata Version: 2.0

となる。

問題の出力以外は、正しく出力出来ているのでここに示すどれかの方法を使えば今回の問題は解決するようだ。解決したが、今一つスッキリしない。

 

14歳と言うと中学生か。

どんな内容なのか気になる。

子供なんかには負けられないな。

ワテも頑張らなアカン‼

スポンサーリンク
ワテ推薦のプログラミングスクールで学ぶ
コメント募集

この記事に関して何か質問とか補足など有りましたら、このページ下部にあるコメント欄からお知らせ下さい。

ASP.NETC#Visual Studio
スポンサーリンク
warekoをフォローする
スポンサーリンク
われこ われこ

コメント