C# の文字列型と最適な例

C# 文字列

この記事では、C# プログラミングでは文字列がどこにでもあるため、理解することが非常に重要な C# 文字列型について説明します。この記事では、文字列のタイプについて説明し、次に文字列操作を行う際に知っておくべき重要な機能について確認します。さらに、null 参照のチェックと文字列リテラルについて確認します。

文字列は参照型です

C# の文字列は参照型です。参照型と値型 については、こちらで学習できます。 文字列は文字の配列であるため、通常、初期化中に文字列のサイズを判断するのは困難です。文字列が値型の場合、スタック メモリ (値型が保持される場所) に格納する作業が複雑になります。これが、文字列を参照型として扱う主な理由です。

文字列参照比較による興味深い異常

2 つの参照を比較するには、オブジェクト クラスの Equal メソッドを使用します。先に進む前に、以下のコードを確認してください。

            var person1 = new Person() { FirstName = "David" };
            var person2 = new Person() { FirstName = "David" };
            Console.WriteLine(object.Equals(person1, person2));//false            

            string strName = "David";
            string strName1 = "David";
            Console.WriteLine(object.Equals(strName, strName1));//true

上記のコードでは、Person クラスの 2 つの参照を比較しています。これは、参照を作成するたびに、ヒープ内に新しいメモリ ロケーションが割り当てられることがわかっているため、false を返します。これが、2 つの異なる参照を比較する最初のケースで起こっていることです。

しかし、2 つの文字列インスタンスを比較している 2 番目のケースでは、それでも結果は true です。これは、CLR が、同じ値を持つ文字列が既に存在するかどうかをチェックし、新しい参照を作成する代わりに同じ文字列を参照するためです。この比較では大文字と小文字が区別されることに注意してください。

文字列は不変です

文字列は参照型ですが、値型として扱われるように不変になっています。以下のコードを確認してください。

            string name = " David ";         
            Console.WriteLine(string.ReferenceEquals("David", name.Trim()));//False

上記のコードは、上記の議論に従って値を true として返すはずですが、name.Trim() が新しい参照を返すため、上記のコードは false の値を返します。

文字列のこの動作により、多くの文字列の連結や操作を行う場合に文字列を使用するとコストがかかります。文字列に対するすべてのアクションが新しい参照の作成につながるからです。

文字列の連結と操作をより効果的に行うために、StringBuilder クラスが導入されました。 ここで、StringBuilder のパフォーマンスが優れている理由を確認できます。

重要な文字列インスタンス メソッド

ここでは、string クラスの重要なメソッドのいくつかについて簡単に説明します。

<オール>
  • ToUpper() – 文字列のすべての文字を大文字に変換します。
  • ToLower() – 文字列のすべての文字を小文字に変換します。
  • SubString() – 開始インデックスと文字数に基づいて、文字列から部分文字列を抽出します。
  • IndexOf() – 特定のキャラクターの外見のインデックスを返します。
  • Trim() – 文字列の最初と最後から空白を削除します。
  • Split() – 渡された文字に基づいて文字列を分割し、文字列の配列を返します。
  • ToUpper() と ToLower() は、パラメーターの 1 つとしてカルチャの不変性を受け入れるためにオーバーロードされます。このパラメーターを指定しないで ToLower() および ToUpper() を実行すると、エンド ユーザーのローカル カルチャに基づいて文字列が変更され、コードにバグが発生する可能性があります。ユーザーの文化に関係なく文字列を変換したい場合は、以下に示すコードを使用する必要があります

                string name = @"I am the ""best"" Developer";
                name.ToLowerInvariant();
                name.ToUpperInvariant();
                name.ToLower(CultureInfo.InvariantCulture);
                name.ToUpper(CultureInfo.InvariantCulture);

    文化不変の比較

    以下のコードを実行すると、2 つの C# 文字列を比較して true になります。私のシステムの現在のカルチャ、つまり en-US、比較は正しいです。

            const string strlocal = "I AM BEST DEVELOPER";
            public static void Main()
            {
                string fromDB = "i am best developer";
                bool result = string.Equals(fromDB.ToUpper(), strlocal);//returns true
            }

    上記のコードでは、strlocal を比較しています fromDB 文字列変数を持つ const C# 文字列変数。 fromDBs を取得していると推測できます 外部ソースからの値。

    しかし、以下に示すように、システムの現在のカルチャをトルコに変更するとします。

            const string strlocal = "I AM BEST DEVELOPER";
            public static void Main()
            {
                Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("tr");
                string fromDB = "i am best developer";
                bool result = string.Equals(fromDB.ToUpper(), strlocal);//returns false
            }

    トルコ文化では fromDB.ToUpper() が「İ AM BEST DEVELOPER」に変換されるため、コードの結果は false です。 (I) 文字の上に余分な .(ドット) があることに注意してください。これは否定的な結果になります。

    この種のバグを防ぐには、カルチャ インバリアント比較を使用する必要があります。この場合、ToUpperInvariant() を使用する必要があり、正しい結果が得られます。

    重要な文字列静的メソッド

    <オール>
  • string.Concat
  • string.Join
  • これらは、以下のコードに示すように、コレクションから文字列を結合または連結する際の厄介な foreach ループを防ぐことができるため、すべてのプログラマーが知っておくべき C# 文字列クラスの 2 つのメソッドです。

                IList names = new List() {"Test", "test1", "Test2" };
                string concat = string.Concat(names);

    そして

                Person per1 = new Person() { Name = "test", Age = 2 };
                Person per2 = new Person() { Name = "test1", Age = 4 };
                Person per3 = new Person() { Name = "tset2", Age = 6 };
    
                IList names = new List();
                names.Add(per1);
                names.Add(per2);
                names.Add(per3);
                string test = string.Join(",", names.Where(p => p.Age > 3));

    ここで、Person は名前と年齢のプロパティを持つクラスです。

    null 参照と文字列の空をチェックする

    文字列を操作しているときに、null 参照または空の文字列について文字列を比較しなければならない機会がたくさんあります。

    上の図では、2 つの方法を使用して文字列の null と空をチェックしています。最初のメソッド、つまり IsNullOrEmpty は空白をチェックしないため、最初のメソッドが false を返すのに対し、IsNullOrWhiteSpace は空白をチェックするのと同じ文字列に対して true を返します。

    C# 6.0 では、文字列参照チェック用の参照チェック演算子がもう 1 つあります。これは、以下のコードに示すように、文字列の null 条件演算子です。

                string name = null;
                string lowercase = name?.ToLower();

    上記のコードは、null であっても文字列を小文字に変更している間、例外をスローしません。

    文字列リテラル逐語

    新しい行の開始 (\n) やタブの挿入 (\t) などに役立つエスケープ文字を文字列に入れたい場合がありますが、これらが文字列の一部である可能性があります。

    このような場合、たとえばファイルやフォルダを指定するときに文字列に \r、\n、\t、または \ を含めたい場合は、コードを @ 文字で開始する必要がありますまたは、以下のコードに示すように、文字列に二重文字を含める

                string name = @"I am the ""best"" Developer";
                Console.WriteLine(name);

    文字列補間

    文字列クラスの Format メソッドを使用して、以下に示す構文を使用して文字列を補間できます。これにより、コードの見栄えが良くなり、読みやすくなります。

                string firstname = "vikram";
                string lastname = "chaudhary";
                Console.WriteLine(string.Format("My name is {0} {1}", firstname, lastname));

    文字列補間は、文字列の先頭に $ 文字を入れるだけで以下の構文を使用することにより、C# 6.0 で実現できます。

                string firstname = "vikram";
                string lastname = "chaudhary";
                Console.WriteLine($"My name is {firstname} {lastname}");

    結論

    C# の文字列型はプログラミングで広く使用されており、文字列クラスの細部を学習することで、コードを明確で理解しやすいものにすることができます。