文字列とC#の文字列の違いは何ですか?


6510

例(ケースに注意してください):

string s = "Hello world!";
String s = "Hello world!";

それぞれの使用に関するガイドラインは何ですか?そして、違いは何ですか?


72
@ORMapper、実際の遺跡stringである字句のC#の構文文法一方System.Stringだけのタイプです。仕様に明記されている明示的な違いに関係なく、あいまいさを伴う可能性のあるこの暗黙の違いはまだあります。言語自体string、実装が(完全に)BCLの特定のクラスを検討する義務がない(まったく)ない方法でサポートする必要があります。
Kirk Woll 14

106
@KirkWoll:言語仕様によると、言語自体はBCLタイプとまったく同じであると見なす必要があります。それはまったく曖昧ではありません。もちろん、C#文法を使用して独自のコンパイラーを実装し、C#言語仕様で定義されているものとは関係のない任意のものに、そのようなすべてのトークンを使用できます。ただし、結果の言語はC#に似ているだけで、C#とは見なされません。stringSystem.String
またはMapper

88
stringSystemのusingディレクティブがなくても使用できます。でそれを行うことはできませんString
Wilsu

14
アルゴルとフォートランから来た人にとって、この議論はに何か問題があることを示していstringます。を短縮する必要がありますSystem.Stringが、エイリアスとしては非常に似ていますが、まったく同じではありません。C#の数年後、しかし、私は簡単に使用しても安全である、と言うだろうstringstring.Format()していない心配しますSystem.String
Roland

8
@Sangeeta何言ってるの?System.Stringクラスがまだある、とstringキーワードはまだそれの別名です。と同じようSystem.Int32int。それらは文字通り同じものです。
クレイグ、

回答:


6105

stringは、C#のエイリアスですSystem.String
したがって、技術的には違いはありません。それはint System.Int32です。

ガイドラインに関してstringは、オブジェクトを参照するときは常に使用することをお勧めします。

例えば

string place = "world";

同様Stringに、クラスを具体的に参照する必要がある場合は、一般的に使用することをお勧めします。

例えば

string greet = String.Format("Hello {0}!", place);

これは、Microsoftが例で使用する傾向があるスタイルです。

StyleCopがC#固有のエイリアスの使用を強制するようになったため、この領域のガイダンスが変更された可能性があります。


163
StyleCopを使用することに決め、それに従うと、その言語に固有のタイプを使用することになります。したがって、C#の場合は、String(Stringの代わりに)、int(Int32の代わりに)、float(Singleの代わりに)になります-stylecop.soyuz5.com/SA1121.html
Dominic Zukiewicz

144
私はいつかエイリアスを使用します。なぜなら、それらは抽象として機能しているので便利になるかもしれないと思ったからです。したがって、知らなくても実装を変更できます。
Rob

37
Visual Studio 2015は、String.Formatをstring.Formatに変更する必要があると言っているので、Microsoftはそのように進んでいると思います。また、静的メソッドには常にStringを使用しています。
Sami Kuhmonen 14

32
これらを読んだところ、いくつかのコメントが単に正しくないことに気づきました。@ DRAirey1やがて、古い方法が依然として最良であることがわかります。疑わしい場合は、Visual Studioを使用せずにC#コードを記述してみてください。これは事実上不可能であり、Web開発作業で時々発生する状況です。@Vlad Stringを使用するために何もインポートする必要はありません。@Abhiあなたのコメントは無意味であり、同様に真実ですstring.Format()。@KlitosGいいえ、そうではありません。それらはすべてまったく同じように動作します。
krowe2

46
実際には違いがあるという発言を付け加えていただけませんか?たとえば、nameof(string)コンパイルされませんが、コンパイルnameof(String)されます。
Jeroen Vannevel 2016

3439

完全を期すために、ここに関連情報の頭脳ダンプがあります...

他の人が指摘したようにstring、はのエイリアスですSystem.String。それらは同じコードにコンパイルされるため、実行時に違いはありません。これは、C#のエイリアスの1つにすぎません。完全なリストは次のとおりです。

object:  System.Object
string:  System.String
bool:    System.Boolean
byte:    System.Byte
sbyte:   System.SByte
short:   System.Int16
ushort:  System.UInt16
int:     System.Int32
uint:    System.UInt32
long:    System.Int64
ulong:   System.UInt64
float:   System.Single
double:  System.Double
decimal: System.Decimal
char:    System.Char

stringおよびを除いてobject、エイリアスはすべて値の型に対するものです。decimal値型ですが、CLRのプリミティブ型ではありません。エイリアスを持たない唯一のプリミティブ型はSystem.IntPtrです。

仕様では、値タイプのエイリアスは「単純タイプ」と呼ばれています。リテラルは、すべての単純型の定数値に使用できます。他の値タイプには、使用可能なリテラル形式はありません。(これをVBと比較してくださいDateTime。VB はリテラルを許可し、エイリアスも持っています。)

エイリアスを使用しなければならない状況が1つあります。列挙型の基礎となる型を明示的に指定する場合です。例えば:

public enum Foo : UInt32 {} // Invalid
public enum Bar : uint   {} // Valid

コロンがなければならないの後の部分-それは仕様定義列挙型の宣言方法の問題だ一体型のの1つのトークンで生産、sbytebyteshortushortintuintlongulongcharとは対照的に、... として生産たとえば、変数宣言で使用されます。他の違いを示すものではありません。

最後に、どちらを使用するかということになります。個人的には、実装にはエイリアスを使用しますが、APIにはCLRタイプを使用します。実装に関してどれを使用するかはそれほど重要ではありません。チーム間の一貫性は良好ですが、他の誰も気にしません。一方、APIで型を参照する場合は、言語に依存しない方法で参照することが本当に重要です。呼び出されたメソッドReadInt32は明確ですが、呼び出されたメソッドにReadIntは解釈が必要です。呼び出し元は、たとえばのintエイリアスを定義する言語を使用している可能性がありますInt16。.NETフレームワークの設計者は、このパターンに従っています。その良い例はBitConverter、クラスにBinaryReaderありConvertます。


82
列挙型の継承状況は興味深いです。列挙にエイリアスを使用する必要がある理由をドキュメントで示すことができますか?それとも既知のバグですか?
JaredPar '19年

149
仕様のセクション14.1にあります(長すぎるため、ここでは簡単に引用できません)。エイリアスを使用する必要があることは明示的には示されていませんが、エイリアスは一種の独自のタイプとして扱われます。それはすべて少し奇妙です。
Jon Skeet、

32
@PiPeepは、大量の賛成投票よりも驚くべきことですが、驚異的な少量の反対投票です(上位5件の投稿の合計は2000件を超えていますが、その中の1つだけが反対票です)。特に、どのコミュニティにも常に「嫌悪者」が存在するという考えを考慮に入れると、それは本当に信じられないほどです。
corsiKa

40
間の1つの興味深いの違いstringとはStringつまりstring' is a keyword in c#, so you can not use it as a variable name.For Ex: 、「HI」=文字列; //compiler error, but String String = "hi"; `は許容されStringます。キーワードではなくIDifireも同様です。
Sanjeev Rai

33
@SanjeevRai:はい。を使用@stringして、stringあたかも最終的な識別子を作成できます。それは一種の脱出メカニズムです。
Jon Skeet 2013年

716

StringSystem.String.NET Frameworkタイプの略です。stringは、 C#言語のエイリアスです System.String。どちらもSystem.StringIL(Intermediate Language)でコンパイルされているため、違いはありません。あなたが好きなものを選んでそれを使ってください。C#でコーディングする場合はstring、C#タイプのエイリアスであり、C#プログラマーによく知られているので、私はそれを好みます。

intSystem.Int32などについても同じことが言えます。


3
`C#でコーディングする場合、C#タイプのエイリアスであり、C#プログラマーによく知られているので、文字列を好みます-C#の人は.NETフレームワークを知らないでしょう。+1は一般的にこれが最良の答えだと思いますが、私が言及する点は奇妙に思えます。
MyDaftQuestions

4
私は個人的には「Int32」を使用することを好みます。値の範囲がすぐにわかるからです。彼らが後のより高いビットのシステムで「int」のタイプをアップグレードしたと想像してみてください。cの 'int'は明らかに「ターゲットプロセッサが最も効率的に動作する整数型」と見なされ、「少なくとも16ビット」と定義されます。そこでは予測可能な一貫性を希望します。ありがとうございました。
Nyerguds

2
@MyDaftQuestions同意する。.netタイプは言語を知らず、タイプは明白であり、どの言語からも独立しているため、一貫して.netタイプを使用することは理にかなっています(すべてのF#またはVBの特異性を知っていますか?)。
ピーター-モニカの復活2017年

5
@Nyerguds単に気にしない理由は2つあります。1つはint、ハードウェアに関係なく、C#言語仕様で32ビット整数として定義されていることです。C#は、霧の中で共有された遺産にもかかわらず、実際にはCではありませんint。64ビット整数に変更すると、仕様と言語に重大な変更が生じます。またlonglong現在64ビット整数であるを再定義する必要があります。心配する必要のないもう1つの理由は、型が変更されることはないため無関係ですが、.NETは抽象的であるため、99%の場合、とにかくそれについて考える必要はありません。;-)
クレイグ

5
@Craig私は多くの古いプロプライエタリなゲームフォーマットを掘り下げていますが、常にそれについて考えなければなりません。そして使用しInt16Int32そしてInt64ある多く、むしろnondescriptiveを使用するよりも、コードでより透明shortintかつlong
Nyerguds

505

提供された型エイリアスをC#で使用することについて私が今まで聞いた最良の答えは、Jeffrey Richterの著書CLR Via C#にあります。彼の3つの理由は次のとおりです。

  • 私は開発者の数は、使用するかどうかわからない、混乱して見てきた文字列または文字列を自分のコードに。C#では、文字列(キーワード)はSystem.String(FCLタイプ)に正確にマッピングされるため、違いはなく、どちらも使用できます。
  • C#では、longSystem.Int64にマップされますが、別のプログラミング言語では、longInt16またはInt32にマップできます。実際、C ++ / CLIは実際にはInt32として長く扱います。ある言語でソースコードを読んでいる人が、別のプログラミング言語でのプログラミングに慣れていると、コードの意図を簡単に誤って解釈する可能性があります。実際、ほとんどの言語では、キーワードとして長く扱われることも、それを使用するコードをコンパイルすることもありません。
  • FCLには、メソッド名の一部として型名を持つ多くのメソッドがあります。たとえば、BinaryReader型はReadBooleanReadInt32ReadSingleなどのメソッドを提供し、System.Convert型はToBooleanToInt32ToSingleなどのメソッドを提供します。次のコードを書くことは合法ですが、floatを含む行は非常に不自然に感じられ、行が正しいかどうかは明らかではありません。
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

だからあなたはそれを持っています。これらはすべて本当に良い点だと思います。しかし、私は自分のコードでジェフリーのアドバイスを使用していることに気づきません。たぶん、C#の世界に行き詰まっているかもしれませんが、コードをフレームワークコードのように見せようとしています。


24
実際の理由のような第2の点の音ではない、使用するstringintなど
MauganRa

15
@MauganRaそして、本の著者は、彼エイリアスを使用しない理由についてそれらの理由をリストアップすることになっています。
tomi.lee.jones

31
「誰かがC#のソースコードを読んでいる場合、別の言語の仕様ではなく、言語の仕様に従って長く解釈する必要があります。」それは要点を完全に逃しています。誰かコードを誤って解釈しようとしているわけではありません。タイプが別のコンテキストでプログラマが日常的に目にするものと異なる意味を持つ場合、脳が間違った結論にジャンプするのは簡単です。我々はすべての間違いを犯します; 明示的に名前が付けられた型を使用すると、これらの間違いが起こりにくくなります。
ダリル

10
+これらの理由は、問題に対する私の感情を要約しています。私が最初にC#でコーディングを始めたとき(Java / C ++ / Cのバックグラウンドから来た)、エイリアスが醜いと思った。私はまだそのように感じていますが、残念ながら世界のほとんどは私に同意していないようです、または彼らは気にしないので小文字を使用します。
gusgorman 2017年

8
@jinzai問題はC#に関するものです。C#ではlong、プラットフォームやコンパイラーに関係なく、符号付き64ビット整数として定義されます。したがって、少なくとも一部のケースでは、はい、それ言語に依存します。
phoog

455

string予約語ですがString、単なるクラス名です。つまり、stringそれ自体を変数名として使用することはできません。

なんらかの理由でstringという変数が必要な場合は、最初のコンパイルのみが表示されます。

StringBuilder String = new StringBuilder();  // compiles
StringBuilder string = new StringBuilder();  // doesn't compile 

文字列と呼ばれる変数名が本当に必要な場合は@、プレフィックスとして使用できます。

StringBuilder @string = new StringBuilder();

もう1つの重要な違い:Stack Overflowはそれらを異なる方法で強調表示します。


20
ローカル@stringの名前はPDBにのみ存在するため、ローカルを呼び出すことは実際にはかなり無意味であることに注意してください。_stringそれとも何かを呼ぶかもしれません。これは、リフレクションを介してアクセスできる名前を持つものにはより意味@stringがあります"string"。メンバーの名前はになります。
Roman Starkov 2013

25
また、変数名として予約語を使用することは、非常にエレガントではないことに注意してください。
Elton

7
OPは、変数名としてストリングまたはストリングを使用することを望んでいません。彼らはこれらのタイプの違いの説明を求めました。あなたの答えは、さらに混乱するIMOを追加するのに役立ちます
Matt Wilko

1
@craigあなたが結び目を結ぶ方法を人々に教えるソフトウェアを書いていたなら?
Simon_Weaver

5
文字列の@Simon_Weaverノット?はは、いいね。:-)もちろん、スレッドのような別の名前を選ぶこともできます。ちょっと待って... D'oh!
クレイグ

391

1つの違いがあります -あなたが使用することはできませんStringなしにusing System;事前に。


14
デフォルトでは、ほとんどの人がこれをファイルの上部に何らかの方法で追加します。すべてではないほとんどの場合、VSはデフォルトでこれを実行します!
IbrarMumtaz 2010

9
デフォルトでusingは、必要なステートメントのみを追加し、不要なものはすべて明示的に削除します。Power Productivity Tools> "[x] Remove and Format Uses on save"
JMD

2
@JMD私は.csテンプレートファイルを変更したので、上部にusingステートメントがありません!また、クラステンプレートをに変更しましたinternal sealed
ErikE

@JMDその機能は嫌いです。変更されていないファイルに変更を加えることがあり、変更セットに含まれる実際の変更を確認することが困難になります。もちろん、私は通常「スパムの使用」を削除しますが、自動的ではなく積極的に削除します。
mg30rg

C#の場合はそうかもしれませんが、すべての.NET言語がそうであるとは限りません。(
Powershellは

311

それは上記でカバーされました。ただし、stringリフレクションでは使用できません。使用する必要がありますString


6
この回答の意味とそれが賛成された理由がわかりません。typeof(string)リフレクションで使用できます。例1:if (someMethodInfo.ReturnType == typeof(string)) { ... }例2:var p = typeof(string).GetProperty("FirstChar", BindingFlags.NonPublic | BindingFlags.Instance);どこで、それはあなたが使用しなければならないということですString、ではありませんかstringType.GetType("String")またはのようなものを試してもType.GetType("string")、名前空間が見つからないため、どちらもクラスを見つけることができません。なんらかのばかげた理由で、大文字と小文字を区別する方法で.Name型を比較"string"する場合、それは正しいです。
Jeppe Stig Nielsen

256

System.Stringは.NET文字列クラスです-C#stringではのエイリアスですSystem.String-使用中は同じです。

ガイドラインについては、あまり行き詰まらず、好きなように使用します。人生にはもっと重要なものがあり、コードはいずれにしても同じです。

あなたが使用している整数のサイズを指定することが必要であるシステムを構築する自分自身を見つけるので、使用する傾向がある場合はInt16Int32UInt16UInt32などそれは使用することがより自然に見えるかもしれないString-と異なる.NET言語間を動き回るとき、それは可能性があります物事をより理解しやすくします-そうでなければ私は文字列とintを使用します。


2
1つだけ選択して、一貫性を保つ。家のスタイルでどこかで作業する場合は、それを使用してください。
アランB

3
残念ながら、スタイルは個人的な好みであり、専用のコード所有者がいない複数のチームにまたがる大規模なコードベースに適用するにはコストがかかりすぎる場合があります。文字列と文字列ではなく、常に注意すべき重要な問題があります。「人生でもっと重要なこと」に戻る
aiodintsov

これは間違いなく好みです。例えば:私は使用することを好むshortintushortuintの代わりに、Int16これは私が学んだ方法です主な理由など、。確かに、Int16経験が少ない人にとってはすぐに理解する方が簡単です。+1私から!
Candleshark、2019年

210

.NETフォーマットの理由から、(エイリアスではなく) 大文字のタイプを使用します。.NET型は他のオブジェクトタイプ(値タイプは、すべての後に、適切なオブジェクトである)と同じ着色されています。

条件と制御キーワード(のようなifswitchおよび、return)小文字と(デフォルトで)着色されたダークブルーです。そして、私はどちらかと言えば、使用方法と形式に不一致がありません。

検討してください:

String someString; 
string anotherString; 

11
次のようなコードも作成しますか?Int32 i = 1; int i = 1ではなく、?文字列のエイリアスが使用可能な場合に、エイリアスを使用しないと一貫性がないようです。
bytedev 2013年

29
@nashwan:実際、そうです。 前者の方が自分の意図に関して読みやすくなるのではなく、Int32 i=1;代わりに使用しますint i = 1;。つまり、32ビットの符号付き整数が必要です。
NotMe

5
まあ、開発者がC#コード(文字列)と.NETコード(文字列)のどちらを書いていると思うかは、すべてに依存すると思います。個人的に私はまずC#を書いていると思います(そして.NETを使用しているのはC#です)。
bytedev 2014

7
@アレックス:私のポイントは、あいまいさをなくすために、コーディングを非常に具体的にすることを好むということでした。
NotMe 2015

22
スペクトルの絶対的な反対側では、私はほぼ常に使用しますvar
tic

192

stringStringすべての方法で同じです(大文字の「S」を除く)。どちらの方法でも、パフォーマンスへの影響はありません。

string構文の強調表示のため、ほとんどのプロジェクトでは小文字が推奨されます


Jeffrey Richterは、ここで起こっているような混乱を正確に回避するために、すべてのケースでCLRタイプ(C#を介したCLR)を使用することをお勧めします。
ジョシュ

明らかに、Sとsのどちらを使用しても、この質問が発生するので、リヒターに反対票を投じます。;)
ブラッドウィルソン

リヒターは、文字列がオプションであってはならないことを意味しました-Microsoftはその文字列をその言語で持つべきではありません。リヒターに反対票を投じることはできません-彼は伝説です!:)
Joe Ratzer、2008年

1
私はエイリアスをまったく持たない方が良いかもしれないことに同意します。しかし、私たちがそれらを持っていることを考えると、それらを使用しても問題ないと思います(ただし、メソッド名などでは使用できません)
Jon Skeet

10
「string」は「String」と同じではありません。Isは「System.String」を意味します。したがって、「String」を使用する場合は、「using System」を指定して名前空間を含める必要があります
ThiagoAlves

185

C#は、CLRと共に使用される言語です。

string C#の型です。

System.String CLRのタイプです。

C#をCLRと共に使用すると、stringにマッピングされSystem.Stringます。

理論的には、Javaバイトコードを生成するC#コンパイラを実装できます。このコンパイラーの賢明な実装は、Javaランタイムライブラリと相互運用するためにおそらくマップstringjava.lang.Stringれます。


1
stringC#のではありません。CLRの型にマップされる予約語です。
CesarGon、2011

@CesarGon:ECMA-334のセクション8.2.1に従って:「C#は一連の事前定義された型を提供します[...]事前定義された参照型はオブジェクトと文字列です。」
Rasmus Faber

10
ECMA-334のセクション9.4.3によると、「string」はキーワードです。:-)セマンティクスに焦点を当てれば「文字列」は型であることに同意しますが、構文に焦点を当てればキーワード(予約語)だと思います。標準は両方の視点を裏付けています(多分あいまいすぎます!)。私にとってOPは構文に関するものなので、私は答えを見るときに構文に焦点を合わせる傾向がありますが、あなたの要点もわかります。さらに、あなたの答えは、現状では、2つの異なるタイプが存在することを意味すると解釈される可能性があります。ストリングとストリングは、そうでない場合です。1つは他のマッピングです。
CesarGon

これについて明確にしましょう。'string'は予約済みのエイリアスです。これは真のデータ型ではありません。それは何か他のものを指すものです。これらのエイリアスをすべて削除して(または単に使用しないだけで)、完全に優れたプログラミング言語を使用できます。
Quarkly 2013

168

このYouTubeビデオは、実際の違いを示しています。

しかし、今は長いテキストの答えです。

我々はについて話すとき.NET二つの異なるものがあるものがある.NETフレームワークや他の言語(存在しC#VB.NETそのフレームワークを使用するなど)。

ここに画像の説明を入力してください

" System.String" aka "String"(大文字の "S")は.NETフレームワークのデータ型であり、 "string"はC#データ型です。

ここに画像の説明を入力してください

簡単に言うと、「文字列」は「文字列」のエイリアス(同じものを別の名前で呼びます)です。したがって、技術的には以下の両方のコードステートメントは同じ出力を提供します。

String s = "I am String";

または

string s = "I am String";

同様に、以下に示すように、他のc#データ型のエイリアスがあります。

オブジェクト:System.Object、文字列:System.String、ブール:System.Boolean、バイト:System.Byte、s バイト:System.SByte、ショート:System.Int16など

プログラマーの観点から見た100万ドルの質問では、「文字列」と「文字列」をいつ使用するのでしょうか。

混乱を避けるために、最初に一貫してそれらの1つを使用してください。ただし、ベストプラクティスの観点から、変数宣言を行う場合は「文字列」(小さな「s」)を使用するのが適切であり、クラス名として使用する場合は「文字列」(大文字の「S」)が推奨されます。

以下のコードでは、左側が変数宣言であり、「string」を使用して宣言されています。右側ではメソッドを呼び出しているので、 "String"の方が賢明です。

string s = String.ToUpper() ;

25
「要するに、「文字列」は「文字列」」のエイリアス(同じものを別の名前で呼びます)です。これは不正解です。エイリアスは "string"です。
Xavier Egea 2014年

3
変数宣言を行う場合は「文字列」(小さな「s」)を使用するのが適切であり、クラス名として使用する場合は「文字列」(大文字の「S」)が推奨されます。この規則はもはや有効ではないようです。VisualStudio 2015を使用してStringそれを記述しようとする場合は、「コードを簡略化する」ことをお勧めしますstring。それを...
Massimiliano Kraus

165

小文字stringはのエイリアスですSystem.String。それらはでも同じですC#

あなたはシステムの種類(使用する必要があるかどうかをめぐる議論がありますSystem.Int32System.Stringなど)タイプまたはC# aliasesintstringなど)。私はあなたがを使うべきだと個人的に信じていますがC# aliases、それは私の個人的な好みにすぎません。


4
それが問題です。「C#」エイリアスではなく、「C」エイリアスです。C#言語にはネイティブの「文字列」や「int」はなく、構文上の砂糖だけです。
Quarkly、2015年

16
C#5言語仕様では、「キーワード文字列は、事前定義されたクラスSystem.Stringのエイリアスにすぎません。85ページ、4.2.4項。すべての高水準言語は、CPU命令セットとバイトコードに対する構文上の砂糖です。
aiodintsov 2016

156

stringは単なるのエイリアスですSystem.String。コンパイラはそれらを同じように扱います。

唯一の実用的な違いは、あなたが言及するように構文の強調表示であり、using Systemそれを使用する場合は記述する必要があることStringです。


文字列を使用するためにシステムにプレフィックスを付ける必要はありません。
Joe Ratzer、2008年

18
あなたは含める必要がありますusing System使用している場合String:そうしないと、次のエラーを取得し、The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
ロナルド

143

どちらも同じです。ただし、コーディングガイドラインの観点からは、のstring代わりに使用することをお勧めしますString。これは一般的に開発者が使用するものです。代わりに使用するなどInt32、私たちが使うはintようintにエイリアスですInt32

FYI「キーワード文字列は、事前定義されたクラスの単なるエイリアスですSystem.String。」-C#言語仕様4.2.3 http://msdn2.microsoft.com/En-US/library/aa691153.aspx


120

他の人が言っているように、彼らは同じです。StyleCopルールは、デフォルトでは、あなたが使用することを強制されますstringC#コードのスタイルとして参照する場合を除き、ベストプラクティス、System.Stringのような静的関数、String.FormatString.JoinString.Concat、など...


4
静的メソッドを除いて、StyleCopが文字列の使用にフラグを付けることを知りませんでした。それは私がいつもそれを使用する方法であると思います:型宣言の文字列と静的メンバーにアクセスするときの文字列。
Goyuix、2011

101

6年5カ月後の新しい答え(去勢)。

一方でstring、常に一定の意味を持つ予約済みのC#のキーワードで、String普通である識別子ものを参照することができます。現在のタイプのメンバーに応じて、現在の名前空間と適用されるusingディレクティブおよびそれらの配置は、とStringは異なる値またはタイプになる可能性がありますglobal::System.String

usingディレクティブが役に立たない 2つの例を示します


まず、Stringある、電流型(またはローカル変数)のは:

class MySequence<TElement>
{
  public IEnumerable<TElement> String { get; set; }

  void Example()
  {
    var test = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
  }
}

IEnumerable<>はと呼ばれる非静的メンバーがFormatなく、拡張メソッドが適用されないため、上記はコンパイルされません。上記の場合、が構文的に唯一の可能性Stringである他のコンテキストで使用することはまだ可能です。たとえば、名前空間とディレクティブに応じてOKにすることができます。String local = "Hi mum!";using

さらに悪いことに:String.Concat(someSequence)usings によっては)Linq拡張メソッドに行く可能性が高いEnumerable.Concatです。静的メソッドには行きませんstring.Concat


次に、Stringが別のタイプである場合、現在のタイプ内にネストされます。

class MyPiano
{
  protected class String
  {
  }

  void Example()
  {
    var test1 = String.Format("Hello {0}.", DateTime.Today.DayOfWeek);
    String test2 = "Goodbye";
  }
}

Exampleメソッドのどちらのステートメントもコンパイルされません。ここにStringは常にピアノの弦がありMyPiano.Stringます。メンバーが存在しstaticない(またはFormat存在しない)(またはその基本クラスから継承されている)。そして、値"Goodbye"をそれに変換することはできません。


4
私は悪魔的なことができると思います:using String = System.Int32; using Int32 = System.String; そしてバグを数えます。
Steve

7
これが正解です。stringですSystem.StringString何でもかまいません。
Dave Cousineau

同意して@DaveCousineau-それがエイリアスのポイントです。StringSystem.Stringオブジェクトに設定されない別のタイプを作成できます。チェックアウト:blog.paranoidcoding.com/2019/04/08/...
のKristopher

「キーワードstringはC#で具体的な意味を持っています。これはSystem.Stringコアランタイムアセンブリに存在するタイプです。ランタイムは本質的にこのタイプを理解し、開発者がstrings.NETで期待する機能を提供します。その存在はC#にとって非常に重要なので、そのタイプが存在しない場合、コンパイラーはコード行の解析を試みる前に終了します。そのためstring、C#コードでは正確で明確な意味があります。C#Stringでは具体的な意味はありませんが、すべての名前ルックアップルールを通過する識別子です。などWidgetStudentなど...」
のKristopher



87

Jon Skeetが述べたように、他のプログラマーの間で一般的な慣習のように思われるものに対して、私は参照タイプであるという事実を強調するためだけに優先Stringします。stringString



78

Ritchersの本から、これをlfoustsの回答に追加したいと思います。

C#言語仕様には、「スタイルの問題として、完全なシステムタイプ名を使用するよりもキーワードを使用する方が好ましい」と記載されています。言語仕様に同意しません。私はFCLタイプ名を使用し、プリミティブタイプ名を完全に回避することを好みます。実際、コンパイラーがプリミティブ型名さえ提供せず、開発者に代わりにFCL型名を使用するように強制したいのですが。ここに私の理由があります:

  • 私は開発者の数は、使用するかどうかわからない、混乱して見てきた文字列 または文字列を自分のコードに。C#では、文字列(キーワード)はSystem.String(FCLタイプ)に正確にマップ されるため、違いはなく、どちらも使用できます。同様に、アプリケーションが32ビットOSで実行されている場合はintが32ビット整数を表し、アプリケーションが64ビットOSで実行されている場合は64ビット整数を表すと開発者が言う開発者もいます。このステートメントは完全に偽です。C#では、intは常にSystem.Int32にマップされるため、コードが実行されているOSに関係なく、32ビット整数を表します。プログラマーが使用する場合Int32のコードでは、この潜在的な混乱も解消されます。

  • C#では、longSystem.Int64にマップされますが、別のプログラミング言語では、longInt16またはInt32にマップできます。実際、C ++ / CLIはInt32として長く扱います。ある言語でソースコードを読んでいる誰かが、別のプログラミング言語でのプログラミングに慣れていると、コードの意図を簡単に誤解する可能性があります。実際、ほとんどの言語では、キーワードとして長く扱われることも、それを使用するコードをコンパイルすることもありません。

  • FCLには、メソッド名の一部として型名を持つ多くのメソッドがあります。たとえば、BinaryReader型はReadBooleanReadInt32ReadSingleなどのメソッドを提供し、System.Convert型はToBooleanToInt32ToSingleなどのメソッドを提供します 。次のコードを書くことは合法ですが、floatを含む行は非常に不自然に感じられ、行が正しいかどうかは明らかではありません。

    BinaryReader br = new BinaryReader(...);
    float val = br.ReadSingle(); // OK, but feels unnatural
    Single val = br.ReadSingle(); // OK and feels good
  • C#を排他的に使用する多くのプログラマーは、他のプログラミング言語をCLRに対して使用できることを忘れがちです。そのため、C#の機能はクラスライブラリコードに侵入します。たとえば、MicrosoftのFCLは、ほぼ独占的にFCLチームにC#や開発者に書かれている、今のようなライブラリにする方法を導入している アレイGetLongLength返し、Int64のある値の長い C#ではなく、Cのような他の言語(中に++ / CLI)。別の例は、System.Linq.EnumerableLongCountメソッドです。

完全なパラグラフを読む前に彼の意見を聞きませんでした。


72

文字列(System.String)は、基本クラスライブラリのクラスです。文字列(小文字)はC#で予約されている作業で、System.Stringのエイリアスです。Int32とintは同じような状況ですBoolean vs. bool。これらのC#言語固有のキーワードを使用すると、Cと同様のスタイルでプリミティブを宣言できます。


67

Stringはキーワードではないため、識別子として使用できますstringが、はキーワードであり、識別子としては使用できません。そして、機能の観点では、両方とも同じです。


67

本当に、それは慣習の問題です。 stringC / C ++スタイルに似ています。一般的な規則では、選択した言語で提供されているショートカットを使用します(int / Int for Int32)。これは「オブジェクト」にdecimalも当てはまります。

理論的にはこれは「INT」に意味するかもしれないいくつかの将来の64ビット標準にポートコードに役立つかもしれないInt64が、それはポイントではない、と私はすべてのアップグレードウィザードが任意の変更を期待するintへの参照Int32安全のためにとにかくだけを。


66

パーティーに遅刻:私はCLRタイプを100%使用します(まあ、C#タイプを使用するよう強制された場合を除いて、最後にいつだったか覚えていません)。

リッチーのCLRの本のように、私はもともとこの数年前に始めました。すべてのCLR言語が最終的にCLR型のセットをサポートできる必要があるため、自分でCLR型を使用すると、より明確で、場合によってはより「再利用可能な」コードが提供されることがわかりました。

私は何年もそれをやってきたので、それは習慣です、そして私はVSがCLRタイプに示す色付けが好きです。

実際の唯一の問題は、オートコンプリートがC#タイプを使用することです。そのため、自動生成されたタイプを再入力して、代わりにCLRタイプを指定します。

また、「int」または「string」が表示されると、1970年代のCコードを見るように、本当に間違っているように見えます。


49

違いはありません。

C#キーワードstringは.NETタイプにマップされますSystem.String-これは、言語の命名規則に準拠するエイリアスです。

同様に、にintマッピングされSystem.Int32ます。


64ビットのビルドでは、intはSystem.Int64(8バイト)にマップされ、32ビットのビルドではSystem.Int32(4バイト)にマップされます
Alex

1
IntPtrとUIntPtrは、プラットフォームに応じてサイズを変更する唯一のタイプです([U] IntPtrまたは実際のポインターのような実際のポインタータイプは無視int*)。
Pダディ

45

ダニエル・ソリスの本からこの問題についての引用があります。

事前定義されたタイプはすべて、基礎となる.NETタイプに直接マップされます。C#タイプ名(文字列)は.NETタイプ(文字列またはSystem.String)の単なるエイリアスであるため、.NET名を使用すると構文的に問題なく動作しますが、これはお勧めできません。C#プログラム内では、.NET名ではなくC#名を使用する必要があります。


41

stringはキーワードであり、stringを識別子として使用することはできません。

文字列はキーワードではないため、識別子として使用できます。

string String = "I am a string";

キーワードstring は、System.Stringキーワードの問題以外のエイリアスです 。この2つはまったく同じです。

 typeof(string) == typeof(String) == typeof(System.String)

2
唯一の小さな違いは、Stringクラスを使用する場合、ファイルの先頭にSystem名前空間をインポートする必要があるのに対し、stringキーワードを使用する場合はこれを行う必要がないことです。
Uttam 2018年

等価ステートメントが失敗する単純なユースケースがあります... blah名前空間で型呼び出し文字列を定義し、その名前空間を等価ステートメントが実行されているファイルにインポートするなどです。
リック

40

はい、それはboolとのように、それらの間に違いはありませんBoolean


40

@JaredPar(C#コンパイラの開発者であり、多作なSOユーザーです!)が、この問題について素晴らしいブログ投稿を書いています。ここで共有する価値があると思います。それは私たちのテーマについての良い見方です。

stringStringはスタイルの議論ではありません

[...]

キーワードstringはC#では具体的な意味を持っています。System.Stringコアランタイムアセンブリに存在するタイプです。ランタイムは本質的にこのタイプを理解し、開発者が.NETの文字列に期待する機能を提供します。その存在はC#にとって非常に重要であり、その型が存在しない場合、コンパイラーはコード行の解析さえ試みる前に終了します。したがってstring、C#コードでは正確で明確な意味があります。

Stringただし、C#では識別子は具体的な意味を持ちません。それはように、すべての名前のルックアップのルールを通過する識別子でありWidgetStudentそれは文字列に結合することができるか、それが別のアセンブリ完全にその目的とは全く異なるかもしれタイプに特異的に結合することができ、等... string。さらに悪いことに、次のようなコードで定義できますString s = "hello"。コンパイルし続けました。

class TricksterString { 
  void Example() {
    String s = "Hello World"; // Okay but probably not what you expect.
  }
}

class String {
  public static implicit operator String(string s) => null;
}

の実際の意味は、String常に名前解決に依存します。つまり、プロジェクト内のすべてのソースファイルと、参照されるすべてのアセンブリで定義されているすべてのタイプに依存します。要するに、それが何を意味するのかを知るにはかなりのコンテキストが必要です。

真の例大多数であることStringstring同じタイプにバインドします。しかし、Stringまだ使用するということは、開発者が正しい答えが1つしかない場所でプログラムを解釈に任せることを意味します。場合はString、間違った型に結合しないことは、コンパイラチームにバグを提出し、一般的に使用して保存されていたかもしれない時間を無駄、時間のデバッグ開発者を残すことができますstring

違いを視覚化する別の方法は、このサンプルを使用することです。

string s1 = 42; // Errors 100% of the time  
String s2 = 42; // Might error, might not, depends on the code

多くの人は、これは情報Stringですが、コードベースがこの名前のタイプを定義することは非常にまれであるため、技術的に正確な使用でも問題ないと主張します。または、Stringそれが定義されている場合、それは悪いコードベースの兆候です。

[...]

あなたはそれが表示されますStringこれらのライブラリのいずれかのために...など反射ヘルパー、シリアライズライブラリ、レクサー、プロトコル、:完全に有効ないくつかの目的のために定義されたStringstringのコードが使用されている場所に応じて、実際の結果があります。

ですから、Stringvs。のstring議論を見るとき、これはスタイルではなく、意味論についてです。文字列を選択すると、コードベースに明確な意味が与えられます。選択Stringは間違いではありませんが、将来の驚きに備えてドアを開いたままにしています。

注:アーカイブのため、ほとんどのブログ投稿をコピー/貼り付けました。一部を無視しているので、できればスキップしてブログ記事を読むことをお勧めします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.