C#v4に同梱されているその新しいキーワードに関する記事をたくさん読みましたが、「動的」と「var」の違いを理解できませんでした。
この記事は私にそれについて考えさせましたが、私はまだ違いを見ることができません。
「var」はローカル変数としてのみ使用できますが、ローカルとグローバルの両方として動的に使用できますか?
動的キーワードなしでいくつかのコードを表示してから、動的キーワード付きで同じコードを表示できますか?
C#v4に同梱されているその新しいキーワードに関する記事をたくさん読みましたが、「動的」と「var」の違いを理解できませんでした。
この記事は私にそれについて考えさせましたが、私はまだ違いを見ることができません。
「var」はローカル変数としてのみ使用できますが、ローカルとグローバルの両方として動的に使用できますか?
動的キーワードなしでいくつかのコードを表示してから、動的キーワード付きで同じコードを表示できますか?
回答:
var
静的に型付けされています-コンパイラとランタイムは型を知っています-それらはいくつかの入力を節約します...以下は100%同一です:
var s = "abc";
Console.WriteLine(s.Length);
そして
string s = "abc";
Console.WriteLine(s.Length);
発生したのは、コンパイラがs
(イニシャライザからの)文字列である必要があると判断したことだけです。どちらの場合も、(IL)でs.Length
(インスタンス)string.Length
プロパティを意味します。
dynamic
ある非常に異なる獣。これはに最も似てobject
いますが、動的ディスパッチを使用します。
dynamic s = "abc";
Console.WriteLine(s.Length);
ここでs
は、と入力されています。それは知りませんstring.Length
、それはわからないので、何についてのs
コンパイル時に。たとえば、次のコードもコンパイルされます(実行されません)。
dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);
実行時(のみ)に、プロパティをチェックしFlibbleBananaSnowball
ます-プロパティを見つけることができず、スパークのシャワーで爆発します。
を使用するとdynamic
、プロパティ、メソッド、演算子などは、実際のオブジェクトに基づいて、実行時に解決されます。COM(ランタイムのみのプロパティを持つことができる)、DLR、またはのような他の動的システムとの通信に非常に便利ですjavascript
。
var
、サブタイプと暗黙のキャストのために、望ましくないタイプが推測される場合があることに注意することが重要です。つまりvar
、暗黙のキャストが発生したときに、予想よりも静的に異なる型を解決した可能性があります(特に、より一般的な型に解決されますが、これに限定されません)。些細な例はobject x = ""
vs. var x = ""
vs. var x = "" as object
ですが、他のより卑劣な(そして現実的な)ケースが発生し、微妙なバグを引き起こす可能性があります。
WriteLine
、呼び出す多くのオーバーロードのどれを呼び出すかを正確に認識しています。この「バインディング」はコンパイル時に発生します。以下の場合にはdynamic
、のタイプが.Length
ある必要がありdynamic
すぎて、それはそれはの過負荷(全てであれば)決定され、実行時までではありませんWriteLine
フィット最高。バインディングは実行時に行われます。
var
Visual Studioでキーワードにカーソルを合わせると、推論されている実際のタイプが表示されます。コンパイル時に型がわかっていることを示します。
varで宣言された変数は、暗黙的に型付けされます。dynamicで宣言された変数は動的に型付けされます。この機能は、RubyやPythonなどの動的言語をサポートするためにCLRに追加されました。
これは、動的宣言は実行時に解決され、var宣言はコンパイル時に解決されることを意味します。
dynamicとvarの違いについて説明します。
dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";
これは機能します。コンパイラーは、動的変数のタイプを再作成できます。
最初にタイプを整数として作成し、その後コンパイラーがタイプを文字列として再作成します
が、varの場合
var v1; // Compiler will throw error because we have to initialized at the time of declaration
var v2 = 1; // Compiler will create v1 as **integer**
v2 = "Suneel Gupta"; // Compiler will throw error because, compiler will not recreate the type of variable
キーワード' var ' を使用する場合、タイプはコンパイラーによってコンパイル時に決定されますが、 ' dynamic 'キーワードを使用する場合、タイプはランタイムによって決定されます。
' var 'キーワードは、コンパイラーが初期化式から型を判別できる、強く暗黙的に型付けされたローカル変数です。LINQプログラミングを行うときに非常に役立ちます。
コンパイラーには、変数の動的タイプに関する情報がありません。そのため、コンパイラはインテリジェンスを表示しません。
コンパイラーは、var 型の格納された値に関するすべての情報を持っているため、コンパイラーはインテリジェンスを表示します。
動的型は関数引数として渡すことができ、関数はオブジェクト型も返すことができますが
、
var型は関数引数として渡すことができず、関数はオブジェクト型を返すことができません。このタイプの変数は、それが定義されたスコープで機能します。
varは、静的型検査(早期バインディング)が適用されることを意味します。dynamicは、動的型チェック(遅延バインディング)が適用されることを意味します。コードに関しては、次のことを考慮してください。
class Junk
{
public void Hello()
{
Console.WriteLine("Hello");
}
}
class Program
{
static void Main(String[] args)
{
var a = new Junk();
dynamic b = new Junk();
a.Hello();
b.Hello();
}
}
これをコンパイルしてILSpyで結果を調べると、コンパイラーがbからのHello()への呼び出しを処理するレイトバインディングコードを追加したことがわかりますが、aにはアーリーバインディングが適用されているため、aはHello () 直接。
例(ILSpy分解)
using System;
namespace ConsoleApplication1
{
internal class Junk
{
public void Hello()
{
Console.WriteLine("Hello");
}
}
}
using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Runtime.CompilerServices;
namespace ConsoleApplication1
{
internal class Program
{
[CompilerGenerated]
private static class <Main>o__SiteContainer0
{
public static CallSite<Action<CallSite, object>> <>p__Site1;
}
private static void Main(string[] args)
{
Junk a = new Junk(); //NOTE: Compiler converted var to Junk
object b = new Junk(); //NOTE: Compiler converted dynamic to object
a.Hello(); //Already Junk so just call the method.
//NOTE: Runtime binding (late binding) implementation added by compiler.
if (Program.<Main>o__SiteContainer0.<>p__Site1 == null)
{
Program.<Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(Binder.InvokeMember(CSharpBinderFlags.ResultDiscarded, "Hello", null, typeof(Program), new CSharpArgumentInfo[]
{
CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
}));
}
Program.<Main>o__SiteContainer0.<>p__Site1.Target(Program.<Main>o__SiteContainer0.<>p__Site1, b);
}
}
}
違いを発見するためにできる最善のことは、このような小さなコンソールアプリを自分で作成し、ILSpyで自分でテストすることです。
1つの大きな違い-動的な戻り値の型を使用できます。
dynamic Foo(int x)
{
dynamic result;
if (x < 5)
result = x;
else
result = x.ToString();
return result;
}
以下は、Dynamic(4.0)とVarの違いを示す簡単な例です。
dynamic di = 20;
dynamic ds = "sadlfk";
var vi = 10;
var vsTemp= "sdklf";
Console.WriteLine(di.GetType().ToString()); //Prints System.Int32
Console.WriteLine(ds.GetType().ToString()); //Prints System.String
Console.WriteLine(vi.GetType().ToString()); //Prints System.Int32
Console.WriteLine(vsTemp.GetType().ToString()); //Prints System.String
**ds = 12;** //ds is treated as string until this stmt now assigning integer.
Console.WriteLine(ds.GetType().ToString()); **//Prints System.Int32**
**vs = 12**; //*Gives compile time error* - Here is the difference between Var and Dynamic. var is compile time bound variable.
シヴァ・マミディ
**
、コード例の文字の存在は強調のみを示すことを意図しており、実際に機能するコードの一部を意図するものではないということです。
これは実用的なデモンストレーションでvar
VS について語る素晴らしいyoutubeビデオですDynamic
。
以下は、スナップショットの詳細な説明です。
Varは早期にバインドされ(静的にチェックされます)、Dynamicは遅くバインドされます(動的に評価されます)。
Varキーワードは、右側のデータを調べ、コンパイル時に左側のデータ型を決定します。つまり、varキーワードは、多くの入力を節約するだけです。文字列データとx変数を指定すると、ツールチップに文字列データタイプが表示される以下の画像をご覧ください。
一方、動的キーワードは完全に異なる目的のためです。動的オブジェクトは実行時に評価されます。たとえば、次のコードでは、実行時に「Length」プロパティが存在するかどうかが評価されます。わざと小さな「l」を入力したので、このプログラムはうまくコンパイルされましたが、実際に実行すると、「length」プロパティのときにエラーが発生しました呼び出されました(SMALL "l")。
動的変数と変数変数はどちらも任意のタイプの値を格納できますが、宣言時に「var」を初期化するために必要です。
コンパイラーには、「動的」タイプの変数に関する情報がありません。varはコンパイラセーフです。つまり、コンパイラには格納された値に関するすべての情報が含まれているため、実行時に問題が発生しません。
動的な型は関数の引数として渡すことができ、関数はそれを返すこともできます。Var型は関数の引数として渡すことができず、関数はオブジェクト型を返すことができません。このタイプの変数は、それが定義されたスコープで機能します。
動的キャストの場合は必須ではありませんが、ストアドタイプに関連するプロパティとメソッドを知っている必要があります。一方、varの場合は、コンパイラーが操作を実行するためのすべての情報を持っているため、キャストする必要はありません。
dynamic:リフレクションまたは動的言語サポートを使用してコーディングする場合、またはCOMオブジェクトを使用してコーディングする場合に便利です。必要なコードの量が少ないためです。
var:linqクエリから結果を取得するときに役立ちます。3.5フレームワークでは、linq機能をサポートするために導入されています。
参考:カウンセリングビャビ
例:
Var strNameList=new List<string>(); By using this statement we can store list of names in the string format.
strNameList.add("Senthil");
strNameList.add("Vignesh");
strNameList.add(45); // This statement will cause the compile time error.
ただし、動的型では、基になる型は実行時にのみ決定されます。動的データ型はコンパイル時にチェックされず、厳密に型指定もされません。動的型に任意の初期値を割り当ててから、新しい型に再割り当てすることができます。その寿命の間の価値。
例:
dynamic test="Senthil";
Console.Writeline(test.GetType()) // System.String
test=1222;
Console.Writeline(test.GetType()) // System.Int32
test=new List<string>();
Console.Writeline(test.GetType()) //System.Collections.Generic.List'1[System.String]
IntelliSenseのサポートも提供していません。linqで作業する場合も、より良いサポートを提供していません。ラムダ式、拡張メソッド、匿名メソッドをサポートしていないためです。
ここに違いがあります
varは静的に型指定(コンパイル時)、動的は動的に型指定(実行時)
varとして宣言された変数はローカルでのみ使用でき、動的変数はparamsとして関数に渡すことができます(関数シグネチャはparamを動的ではなくvarとして定義できます)。
動的の場合、プロパティの解決は実行時に行われますが、varの場合はそうではありません。つまり、動的に宣言された変数は、存在する場合と存在しない場合があるメソッドを呼び出すことができるため、コンパイラはエラーをスローしません。
varで型キャストすることはできませんが、dynamicで可能です(オブジェクトをvarとしてではなくdynamicとしてキャストできます)。
アルン・ビジャイラガハヴァン