web-dev-qa-db-ja.com

動的(C#4)とvarの違いは何ですか?

C#v4に同梱されている新しいキーワードに関する記事をたくさん読みましたが、「動的」と「var」の違いを理解できませんでした。

この記事 考えさせられましたが、まだ違いは見られません。

「var」はローカル変数としてのみ使用できますが、ローカルおよびグローバルの両方として動的に使用できますか?

動的キーワードなしのコードをいくつか表示してから、動的キーワード付きの同じコードを表示できますか?

192
Ivan Prodanov

varは静的型指定です-コンパイラーとランタイムknow型-それらは単に型付けを節約します...以下は100%同じです:

var s = "abc";
Console.WriteLine(s.Length);

そして

string s = "abc";
Console.WriteLine(s.Length);

起こったことは、コンパイラsが文字列(初期化子から)でなければならないことを理解したことだけでした。どちらの場合でも、s.Lengthは(インスタンス)string.Lengthプロパティを意味することが(ILで)認識されます。

dynamicvery別の獣です。 objectに最も似ていますが、動的ディスパッチを使用します。

dynamic s = "abc";
Console.WriteLine(s.Length);

ここでは、s動的としてと入力されます。コンパイル時にanythingsを知らないため、string.Lengthを知りません。たとえば、次もコンパイルします(実行はしません):

dynamic s = "abc";
Console.WriteLine(s.FlibbleBananaSnowball);

実行時(のみ)、FlibbleBananaSnowballプロパティのcheck-見つからず、火花のシャワーで爆発します。

dynamicを使用すると、実際のオブジェクトに基づいて、プロパティ/メソッド/演算子/などが解決されます実行時。 COM(実行時のみのプロパティを持つことができる)、DLR、またはjavascriptなどの他の動的システムと通信するのに非常に便利です。

441
Marc Gravell

varで宣言された変数は暗黙のうちにstaticallyに入力されます。 dynamicで宣言された変数は動的に型指定されます。この機能は、RubyやPythonなどの動的言語をサポートするためにCLRに追加されました。

これは、dynamic宣言が実行時に解決されること、var宣言がコンパイル時に解決されることを意味することを付け加える必要があります。

57
HVS

dynamicvarの違いを説明します。

dynamic d1;
d1 = 1;
d1 = "http://mycodelogic.com";

これは動作します。コンパイラはdynamic変数のタイプを再作成できます。
最初にintegerとして型を作成し、その後コンパイラはstringとして型を再作成します
ただし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プログラミングを行うときに非常に役立ちます。
コンパイラには、変数のdynamicタイプに関する情報がありません。そのため、コンパイラはインテリジェンスを表示しません。
コンパイラーはvarタイプの保存値に関するすべての情報を持っているため、コンパイラーはインテリジェンスを表示します。
動的型は関数の引数として渡すことができ、関数はオブジェクト型を返すこともできます
しかし
var型は関数の引数として渡すことができず、関数はオブジェクト型を返すことができません。このタイプの変数は、それが定義されたスコープで機能します。
39
Suneel Gupta

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()の呼び出しを処理する遅延バインディングコードを追加していることがわかります。 () 直接。

例えば(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で自分でテストすることです。

14
series0ne

大きな違いの1つは、動的な戻り型を使用できることです。

dynamic Foo(int x)
{
    dynamic result;

    if (x < 5)
      result = x;
    else
      result = x.ToString();

    return result;
}
12
user2382351

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.

シヴァ・マミディ

10
Shiva Mamidi

varは、通常の型宣言の省略形であり、コンパイラに正しい型を推測させます。

dynamicは新しい(静的)型であり、コンパイラではなく実行時にすべてのチェックが行われます。

7
gimel

Varで宣言された変数の型はコンパイラーによって決定されます。これは型の名前を指定するためのショートカットであり、それ以上のことはありません。

しかし、動的は実行時に決定され、コンパイラは実際の型を認識せず、その変数を使用したすべてのメソッド/フィールド/プロパティアクセスは実行時に解決されます。

4
Richard

これ は、var VS Dynamicについて実用的なデモンストレーションを行う素敵なYouTubeビデオです。

以下は、スナップショットの詳細な説明です。

Varは早期にバインド(静的にチェック)され、動的はレイトバインド(動的に評価)されます。

Varキーワードは右側のデータを見てから、コンパイル時に左側のデータ型を決定します。つまり、varキーワードを使用すると、多くのことを入力する手間が省けます。以下の画像をご覧ください。文字列データとx変数を指定すると、ツールヒントに文字列データ型が表示されます。

enter image description here

一方、動的キーワードはまったく異なる目的のためのものです。動的オブジェクトは実行時に評価されます。たとえば、以下のコードでは、実行中に「Length」プロパティが存在するかどうかが評価されます。意図的に小さな「l」を入力したため、このプログラムは正常にコンパイルされましたが、実際に実行すると「length」プロパティのときにエラーがスローされました呼ばれた(SMALL "l")。

enter image description here

3
  1. 変数および動的定義タイプ。
  2. コンパイル時のvarは、実行時のvarです。
  3. var宣言と初期化では、両方とも定数変数のように必須です。
  4. 動的初期化では、実行時に読み取り専用変数のようにすることができます。
  5. var型では、初期化時に次に決定される型は何も変更できませんが、
  6. dynamicは、ユーザー定義のデータ型でも任意の型を採用できます。
2
shhhhh

動的変数とvar変数はどちらも任意のタイプの値を格納できますが、宣言時に 'var'を初期化するために必要です。

コンパイラには、変数の「動的」タイプに関する情報がありません。 varはコンパイラに対して安全です。つまり、コンパイラは格納された値に関するすべての情報を保持しているため、実行時に問題が発生することはありません。

動的型は関数の引数として渡すことができ、関数はそれを返すこともできます。 Var型は関数の引数として渡すことができず、関数はオブジェクト型を返すことができません。このタイプの変数は、それが定義されたスコープで機能します。

動的なキャストの場合は必要ありませんが、ストアド型に関連するプロパティとメソッドを知る必要があります。一方、varには、操作を実行するためのすべての情報があるため、キャストする必要はありません。

dynamic:リフレクションまたは動的言語サポートを使用してコーディングするとき、またはCOMオブジェクトでコーディングするときに便利です。これは、より少ない量のコードを記述する必要があるためです。

var:linqクエリから結果を取得するときに役立ちます。 3.5フレームワークでは、linq機能をサポートするために導入します。

参照: カウンセリングバイアヒ

2
  1. Var(Implicit typed local variable)キーワードは、ローカル変数を定義するために使用されます。Varの場合、基礎となるデータ型は、初期割り当てに基づいてコンパイル時に決定されます。 Var型と互換性のない値を保存しようとすると、コンパイル時エラーが発生します。

例:

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を使用するときのサポートも向上していません。ラムダ式、拡張メソッド、匿名メソッドをサポートしていないためです。

1
kuttychutty

ここに違いがあります

  • varは静的に型指定され(コンパイル時)、dynamicは動的に型指定されます(実行時)

  • Varとして宣言された変数はローカルでのみ使用でき、動的変数は関数にパラメーターとして渡すことができます(関数シグネチャはvarを動的としてパラメーターを定義できますが、varは定義できません)。

  • 動的では、プロパティの解決は実行時に行われます。それは、コンパイル時に動的として宣言された変数が存在する場合と存在しない場合があるメソッドを呼び出すことができるため、コンパイラがエラーをスローしないことを意味するvarの場合ではありません.

  • Varを使用した型キャストは不可能ですが、dynamicを使用すると可能です(varとしてではなくdynamicとしてオブジェクトをキャストできます)。

Arun Vijayraghavan

1

Dynamicとvarを混同しないでください。 varを使用してローカル変数を宣言することは、コンパイラーが式から特定のデータ型を推測する構文上のショートカットにすぎません。 varキーワードはメソッド内でローカル変数を宣言するためにのみ使用できますが、dynamicキーワードはローカル変数、フィールド、および引数に使用できます。式をvarにキャストすることはできませんが、式を動的にキャストすることはできます。 dynamicで宣言された変数を初期化する必要はありませんが、varを使用して宣言された変数を明示的に初期化する必要があります。

1
Kartik M