243

以前に、キーワードを使用する例が非常に多く見られる理由についてvar質問したところ、匿名型にのみ必要であるにもかかわらず、コードの記述を「より速く」/より簡単にし、「理由だけ」で使用されているという答えが得られました。

このリンク (「C# 3.0 - Var Isn't Objec」)をたどるvarと、IL で正しい型にコンパイルされることがわかりました (記事の途中に表示されます)。

私の質問は、IL コードがキーワードを使用すると、さらにどれくらいvarかかるかということです。それがどこでも使用された場合、コードのパフォーマンスが測定可能なレベルに近づくでしょうか?

4

12 に答える 12

324

キーワード用の追加の IL コードはありませんvar。結果の IL は、非匿名型と同じになるはずです。コンパイラが、使用する予定の型を特定できないためにその IL を作成できない場合は、コンパイラ エラーが発生します。

唯一のトリックはvar、タイプを手動で設定する場合に、インターフェイスまたは親タイプを選択した正確なタイプを推測することです。

于 2008-12-10T17:21:40.507 に答える
75

Joel が言うように、コンパイラはコンパイル時に var の型を決定します。実質的には、キーストロークを節約するためにコンパイラが実行するトリックにすぎません。たとえば、

var s = "hi";

に置き換えられます

string s = "hi";

IL が生成される前に、コンパイラによって。生成された IL は、文字列を入力した場合とまったく同じになります。

于 2008-12-10T17:24:20.157 に答える
30

まだ誰もリフレクターについて言及していないので...

次のC#コードをコンパイルする場合:

static void Main(string[] args)
{
    var x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

次に、その上でリフレクターを使用すると、次のようになります。

// Methods
private static void Main(string[] args)
{
    string x = "hello";
    string y = "hello again!";
    Console.WriteLine(x);
    Console.WriteLine(y);
}

したがって、答えは明らかに実行時のパフォーマンスに影響がないことです。

于 2009-11-18T14:42:02.213 に答える
17

次のメソッドの場合:

   private static void StringVsVarILOutput()
    {
        var string1 = new String(new char[9]);

        string string2 = new String(new char[9]);
    }

IL 出力は次のとおりです。

        {
          .method private hidebysig static void  StringVsVarILOutput() cil managed
          // Code size       28 (0x1c)
          .maxstack  2
          .locals init ([0] string string1,
                   [1] string string2)
          IL_0000:  nop
          IL_0001:  ldc.i4.s   9
          IL_0003:  newarr     [mscorlib]System.Char
          IL_0008:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_000d:  stloc.0
          IL_000e:  ldc.i4.s   9
          IL_0010:  newarr     [mscorlib]System.Char
          IL_0015:  newobj     instance void [mscorlib]System.String::.ctor(char[])
          IL_001a:  stloc.1
          IL_001b:  ret
        } // end of method Program::StringVsVarILOutput
于 2011-02-22T20:15:20.613 に答える
14

C# コンパイラは、varコンパイル時に変数の実際の型を推測します。生成された IL に違いはありません。

于 2008-12-10T17:23:28.943 に答える
8

あなたは読んだ内容を正しく理解していないと思います。正しい型にコンパイルされた場合、違いはありません。私がこれを行うとき:

var i = 42;

コンパイラはそれが int であることを認識し、私が書いたかのようにコードを生成します

int i = 42;

リンク先の投稿にあるように、同じタイプにコンパイルされます。これは実行時チェックでも、追加のコードを必要とするものでもありません。コンパイラは、型が何である必要があるかを判断し、それを使用します。

于 2008-12-10T17:30:41.113 に答える
5

var を使用しても実行時のパフォーマンス コストは発生しません。ただし、コンパイラは型を推測する必要があるため、コンパイルのパフォーマンス コストが発生すると思われますが、これは無視できる可能性が最も高いでしょう。

于 2008-12-10T17:41:10.450 に答える
3

私は、Web 記事やガイドの文章では常に var という言葉を使用しています。

オンライン記事のテキストエディタの幅が狭い。

これを書くと:

SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

上記のレンダリングされたプレコード テキストが長すぎて、ボックスからはみ出し、非表示になっていることがわかります。完全な構文を表示するには、右にスクロールする必要があります。

そのため、私は Web 記事の執筆で常にキーワード var を使用しています。

var coolClass = new SomeCoolNameSpace.SomeCoolClassName.SomeCoolSubClassName();

レンダリングされたプリコード全体が画面内にちょうど収まります。

実際には、オブジェクトを宣言するために var を使用することはめったになく、オブジェクトをより速く宣言するために IntelliSense に依存しています。

例:

SomeCoolNamespace.SomeCoolObject coolObject = new SomeCoolNamespace.SomeCoolObject();

ただし、メソッドからオブジェクトを返す場合は、var を使用してコードをより速く記述します。

例:

var coolObject = GetCoolObject(param1, param2);
于 2014-07-21T01:55:18.803 に答える
3

コンパイラが自動型推論を実行できる場合、パフォーマンスに問題はありません。これらは両方とも同じコードを生成します

var    x = new ClassA();
ClassA x = new ClassA();

ただし、型を動的に構築している場合 (LINQ ...)varは唯一の質問であり、ペナルティを判断するために比較する他のメカニズムがあります。

于 2008-12-10T17:28:33.863 に答える
0

場合によっては、このコードを使用してみてください。

式は「OBJECT」に変換され、パフォーマンスが大幅に低下しますが、これは孤立した問題です。

コード:

public class Fruta
{
    dynamic _instance;

    public Fruta(dynamic obj)
    {
        _instance = obj;
    }

    public dynamic GetInstance()
    {
        return _instance;
    }
}

public class Manga
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
    public int MyProperty3 { get; set; }
}

public class Pera
{
    public int MyProperty { get; set; }
    public int MyProperty1 { get; set; }
    public int MyProperty2 { get; set; }
}

public class Executa
{
    public string Exec(int count, int value)
    {
        int x = 0;
        Random random = new Random();
        Stopwatch time = new Stopwatch();
        time.Start();

        while (x < count)
        {
            if (value == 0)
            {
                var obj = new Pera();
            }
            else if (value == 1)
            {
                Pera obj = new Pera();
            }
            else if (value == 2)
            {
                var obj = new Banana();
            }
            else if (value == 3)
            {
                var obj = (0 == random.Next(0, 1) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance());
            }
            else
            {
                Banana obj = new Banana();
            }

            x++;
        }

        time.Stop();
        return time.Elapsed.ToString();
    }

    public void ExecManga()
    {
        var obj = new Fruta(new Manga()).GetInstance();
        Manga obj2 = obj;
    }

    public void ExecPera()
    {
        var obj = new Fruta(new Pera()).GetInstance();
        Pera obj2 = obj;
    }
}

上記は ILSPY での結果です。

public string Exec(int count, int value)
{
    int x = 0;
    Random random = new Random();
    Stopwatch time = new Stopwatch();
    time.Start();

    for (; x < count; x++)
    {
        switch (value)
        {
            case 0:
                {
                    Pera obj5 = new Pera();
                    break;
                }
            case 1:
                {
                    Pera obj4 = new Pera();
                    break;
                }
            case 2:
                {
                    Banana obj3 = default(Banana);
                    break;
                }
            case 3:
                {
                    object obj2 = (random.Next(0, 1) == 0) ? new Fruta(new Manga()).GetInstance() : new Fruta(new Pera()).GetInstance();
                    break;
                }
            default:
                {
                    Banana obj = default(Banana);
                    break;
                }
        }
    }
time.Stop();
return time.Elapsed.ToString();
}

このコードを実行したい場合は、次のコードを使用して、時間差を取得します。

        static void Main(string[] args)
    {
        Executa exec = new Executa();            
        int x = 0;
        int times = 4;
        int count = 100000000;
        int[] intanceType = new int[4] { 0, 1, 2, 3 };

        while(x < times)
        {                
            Parallel.For(0, intanceType.Length, (i) => {
                Console.WriteLine($"Tentativa:{x} Tipo de Instancia: {intanceType[i]} Tempo Execução: {exec.Exec(count, intanceType[i])}");
            });
            x++;
        }

        Console.ReadLine();
    }

よろしく

于 2019-05-24T00:25:06.073 に答える