私は C# を学ぼうとしている PHP Web プログラマーです。
変数を作成するときに C# でデータ型を指定する必要がある理由を知りたいです。
Class classInstance = new Class();
クラスインスタンスの前にデータ型を知る必要があるのはなぜですか?
私は C# を学ぼうとしている PHP Web プログラマーです。
変数を作成するときに C# でデータ型を指定する必要がある理由を知りたいです。
Class classInstance = new Class();
クラスインスタンスの前にデータ型を知る必要があるのはなぜですか?
他の人が言ったように、C# は static/strongly-typed です。しかし、私はあなたの質問を「なぜこのように C# を静的/強く型付けする必要があるのですか? これには動的言語よりもどのような利点がありますか?」
それを念頭に置いて、多くの正当な理由があります。
可読性/保守性 コードを読む将来の開発者に、コードがどのように機能するかについて、より多くの情報を提供しています。特定の変数が特定の種類の値を保持することを意図しているという情報を追加し、プログラマーがその変数の目的を判断するのに役立ちます。
たとえば、Microsoft のスタイル ガイドラインでは、VB6 プログラマーは変数名に型のプレフィックスを付けることが推奨されているのに、VB.Net プログラマーはそうではないとされているのは、おそらくこれが理由です。
パフォーマンスこれは最も弱い理由ですが、遅延バインディング/ダック タイピングが遅くなる可能性があります。最後に、変数は特定の方法で構造化されたメモリを参照します。厳密な型がないと、ある方法で物理的に構造化されたメモリを論理的に別の方法で構造化されているかのように使用するため、プログラムは実行時に舞台裏で追加の型検証または変換を行う必要があります。
この点を含めることをためらっています。最終的には、厳密に型指定された言語でもこれらの変換を行わなければならないことがよくあるからです。厳密に型指定された言語は、変換の正確なタイミングと範囲をプログラマーに任せ、必要がない限り余分な作業を行わないというだけです。また、プログラマーがより有利なデータ型を強制することもできます。しかし、これらは実際にはプラットフォームではなくプログラマーの属性です。
優れた動的言語はプログラマーよりも優れた選択をすることが多いということを除けば、それ自体はこの点を省略する理由にはなりません。これは、動的言語が多くのプログラマーがより高速なプログラムを作成するのに役立つことを意味します。それでも、優れたプログラマーにとっては、厳密に型指定された言語の方が高速になる可能性があります。
あるいは、なぜ同じ行で同じ変数に対してクラス名を 2 回指定しなければならないのか疑問に思っていたのではないでしょうか? 答えは 2 つあります。
var
では、多くの場合、型名の代わりにキーワードを使用できます。この方法で作成された変数は引き続き静的に型付けされますが、型はコンパイラによって推測されるようになりました。それは単に言語がどのように設計されたかです。C# は C スタイルの言語であり、左側に型があるというパターンに従います。
C# 3.0 以降では、多くの場合、ローカル型推論を使用してこれを回避できます。
var variable = new SomeClass();
しかし同時に、LHS でまだ型を宣言していると主張することもできます。コンパイラにそれを選んでもらいたいだけです。
編集
ユーザーの元の質問のコンテキストでこれを読んでください
変数名の前に [クラス名] が必要なのはなぜですか?
このスレッドの他のいくつかの回答についてコメントしたいと思いました。多くの人が「C# は静的型です」と答えています。ステートメントは真実ですが (C# は静的に型付けされています)、質問とはほとんど関係ありません。静的型付けでは、型名が変数名の左側にある必要はありません。確かにそれは役に立ちますが、それは言語設計者の選択であり、静的型付き言語に必要な機能ではありません。
これらは、F# などの他の静的型付け言語を考慮することで簡単に証明できます。F# の型は変数名の右側に表示され、多くの場合、完全に省略できます。反例もいくつかあります。たとえば、PowerShell は非常に動的で、含まれている場合はすべての型を左側に配置します。
主な理由の 1 つは、割り当ての左側の型が左側の型の親型 (またはその型に実装されているインターフェイス) である限り、さまざまな型を指定できることです。
たとえば、次のタイプがあるとします。
class Foo { }
class Bar : Foo { }
interface IBaz { }
class Baz : IBaz { }
C# ではこれを行うことができます。
Foo f = new Bar();
IBaz b = new Baz();
はい、ほとんどの場合、コンパイラは代入から変数の型を推測できvar
ますが (キーワードの場合と同様)、上記の理由により推測できません。
編集:注文のポイントとして-C#は強く型付けされていますが、重要な違い(この議論に関する限り)は、実際には静的に型付けされた言語でもあるということです。つまり、C# コンパイラはコンパイル時に静的な型チェックを行います。
C# は、C や C++ のように、静的に型指定され、厳密に型指定された言語です。これらの言語では、すべての変数を特定の型として宣言する必要があります。
結局、アンダース・ヘルスバーグがそう言ったからです...
次のように、最初の [クラス名] が 2 番目の [クラス名] と異なる状況が多いため、前に [クラス名] が必要です。
IMyCoolInterface obj = new MyInterfaceImplementer();
MyBaseType obj2 = new MySubTypeOfBaseType();
など。タイプを明示的に指定したくない場合は、「var」という単語を使用することもできます。
クラスインスタンスの前にデータ型を知る必要があるのはなぜ ですか?
あなたはそうしない!右から左に読んでください。変数を作成し、それを型安全な変数に格納して、後で使用するためにその変数の型を把握します。
次のスニペットを考えてみてください。実行時までエラーが表示されない場合、デバッグは悪夢です。
void FunctionCalledVeryUnfrequently()
{
ClassA a = new ClassA();
ClassB b = new ClassB();
ClassA a2 = new ClassB(); //COMPILER ERROR(thank god)
//100 lines of code
DoStuffWithA(a);
DoStuffWithA(b); //COMPILER ERROR(thank god)
DoStuffWithA(a2);
}
new Class()を数値または文字列に置き換えることができると考えている場合、構文ははるかに理にかなっています。次の例は少し冗長かもしれませんが、このように設計されている理由を理解するのに役立ちます。
string s = "abc";
string s2 = new string(new char[]{'a', 'b', 'c'});
//Does exactly the same thing
DoStuffWithAString("abc");
DoStuffWithAString(new string(new char[]{'a', 'b', 'c'}));
//Does exactly the same thing
他の人が指摘したように、C# は強力な静的型付け言語です。
作成しようとしている型が何であるかを前もって述べると、不正な値を代入しようとすると、コンパイル時に警告が表示されます。メソッドで受け入れるパラメーターのタイプを前もって述べておくことで、それを期待していないメソッドにナンセンスを誤って渡したときに、同じコンパイル時の警告を受け取ります。あなたに代わって、パラノイアのオーバーヘッドを取り除きます。
最後に、C# (および他の多くの言語) には、PHP のような「意味をなさない場合でも、何でも変換する」というばかげた考え方がありません。それが役立つよりも。
C# 3.0 では、'var' キーワードを使用できます。これは、静的な型推論を使用して、コンパイル時に変数の型を判断します。
var foo = new ClassName();
それ以降、変数 'foo' はタイプ 'ClassName' になります。
言及されていないことの 1 つは、C# が CLS (Common Language Specification) 準拠の言語であることです。これは、.NET 言語が他の .NET 言語と相互運用できるようにするために遵守しなければならない規則のセットです。
つまり、C# はこれらのルールを守っているだけです。この MSDN の記事を引用するには:
CLS は、さまざまな言語で利用できるように開発者が信頼できる一連の機能を定義することにより、言語の相互運用性を強化および保証するのに役立ちます。CLS は、CLS 準拠の要件も確立します。これらは、マネージ コードが CLS に準拠しているかどうか、および特定のツールが CLS 機能を使用するマネージ コードの開発をどの程度サポートしているかを判断するのに役立ちます。
コンポーネントが他のコード (派生クラスを含む) に公開する API で CLS 機能のみを使用する場合、CLS をサポートする任意のプログラミング言語からコンポーネントにアクセスできることが保証されます。CLS 規則に準拠し、CLS に含まれる機能のみを使用するコンポーネントは、CLS 準拠のコンポーネントと呼ばれます。
CLS の一部は、Common Type Systemである CTS です。
頭字語が足りない場合は、CLI、ILasm/MSIL、CLR、BCL、FCL など、.NET にはさらに多くの頭字語があります。
c# は、c++ や Java のように厳密に型指定された言語です。したがって、変数の型を知る必要があります。var キーワードを使用して、C# 3.0 で少しごまかすことができます。これにより、コンパイラは型を推測できます。
これが、強く型付けされた言語と弱く型付けされた言語の違いです。C# (および C、C++、Java、および最も強力な言語) は厳密に型指定されるため、変数の型を宣言する必要があります。
データを保持する変数を定義するとき、それらの変数が保持するデータのタイプを指定する必要があります。次に、コンパイラは、データに対して行っていることが理にかなっていること、つまりルールに従っているかどうかをチェックします。たとえば、テキストを数値に格納することはできません - コンパイラはそれを許可しません。
int a = "fred"; // Not allowed. Cannot implicitly convert 'string' to 'int'
変数 a は int 型であり、それにテキスト文字列である値「fred」を割り当てると、ルールが破られます。コンパイラは、この文字列のいかなる種類の変換も行うことができません。
静的型付けにより、コンパイラはより適切な最適化を行い、特定のステップをスキップすることもできます。たとえば、引数だけが異なる同じ名前の複数のメソッドまたは演算子がある場合のオーバーロードを考えてみましょう。動的言語では、ランタイムは、最適な一致を判断するために各バージョンを評価する必要があります。このような静的言語では、最終的なコードは単に適切なオーバーロードを直接指しています。
静的型付けは、コードのメンテナンスとリファクタリングにも役立ちます。私のお気に入りの例は、多くのハイエンド IDE の名前変更機能です。静的型付けのおかげで、IDE はコード内のすべての識別子を確実に検出し、同じ名前の無関係な識別子をそのままにしておくことができます。
まだ言及されていたかどうかはわかりませんでしたが、C# 4.0 ではdynamic
キーワードを介して動的チェックが導入されました。必要がないときは避けたいと思うと思いますが。
C# は厳密に型指定された言語であるため
静的型付けとは、コンパイラが実行時ではなくコンパイル時に何らかのチェックを実行できることを意味します。すべての変数は、静的タイプの特定のタイプまたは強力なタイプです。C# は確実に強く型付けされています。