MyVar ile return (myVar) arasında bir fark var mı?


87

Bir örnek C # koduna bakıyordum ve bir örneğin dönüşü () 'lerin içine sardığını fark ettim.

Ben hep yaptım:

return myRV;

Şunları yapmakta bir fark var mı:

return (myRV);

Yanıtlar:


229

GÜNCELLEME: Bu soru, blogumun 12 Nisan 2010 tarihli konusuydu . Eğlenceli soru için teşekkürler!

Pratikte hiçbir fark yoktur.

Gelen teori bir fark var olabilir. C # belirtiminde bunun bir fark oluşturabileceği üç ilginç nokta vardır.

İlk olarak, anonim işlevlerin temsilci türlerine ve ifade ağaçlarına dönüştürülmesi. Aşağıdakileri göz önünde bulundur:

Func<int> F1() { return ()=>1; }
Func<int> F2() { return (()=>1); }

F1açıkça yasaldır. Mı F2? Teknik olarak hayır. Spesifikasyon 6.5 bölümünde lambda ifadesinden uyumlu bir temsilci türüne bir dönüşüm olduğunu söylüyor . Bu bir lambda ifadesi mi? Hayır . Lambda ifadesi içeren parantezli bir ifadedir .

Visual C # derleyicisi burada küçük bir özellik ihlali yapar ve parantezi sizin için atar.

İkinci:

int M() { return 1; }
Func<int> F3() { return M; }
Func<int> F4() { return (M); }

F3yasaldır. Mı F4? Hayır. Bölüm 7.5.3, parantezli bir ifadenin bir yöntem grubu içermeyebileceğini belirtir. Yine, size kolaylık sağlamak için şartnameyi ihlal ediyor ve dönüşüme izin veriyoruz.

Üçüncü:

enum E { None }
E F5() { return 0; }
E F6() { return (0); }

F5yasaldır. Mı F6? Hayır. Spesifikasyon, değişmez sıfırdan numaralandırılmış herhangi bir türe bir dönüşüm olduğunu belirtir. " (0)" değişmez sıfır değil, bir parantez ve ardından değişmez sıfır ve ardından bir parantez geliyor. Buradaki şartnameyi ihlal ediyoruz ve aslında sıfıra eşit herhangi bir derleme zamanı sabiti ifadesine izin veriyoruz , sadece sıfıra değil.

Bu nedenle, her durumda, teknik olarak yasadışı olmasına rağmen, bundan kurtulmanıza izin veriyoruz.


12
@ Jason: İlk iki vakadaki şartname ihlallerinin asla yakalanmayan hatalar olduğuna inanıyorum. İlk bağlama geçişi, ifadeleri vaktinden önce optimize etme konusunda tarihsel olarak çok agresif olmuştur ve bunun sonuçlarından biri, parantezlerin olması gerekenden çok erken, çok erken atılmasıdır. Hemen hemen her durumda, tüm bunlar, sezgisel olarak aşikar olan programları olması gerektiği gibi çalıştırıyor, bu yüzden bu konuda çok endişelenmiyorum. Üçüncü vakanın analizi burada: blogs.msdn.com/ericlippert/archive/2006/03/28/…
Eric Lippert

6
Teoride, uygulamada, orada olan bir fark (ı Mono bu 3 vaka izin verdiğinden emin eğer değilim ve başka herhangi bir C # derleyici bilmiyorum, bu yüzden ya pratikte uygulamada bir fark olabilir de olmayabilir de). C # spesifikasyonunun ihlal edilmesi, kodunuzun tamamen taşınabilir olmayacağı anlamına gelir. Bazı C # derleyicileri, Visual C # 'dan farklı olarak, bu belirli durumlarda spesifikasyonu ihlal etmeyebilir.
Brian

18
@Bruno: Tek gereken, belirli bir konuda yaklaşık sekiz veya on bin saat çalışmak ve siz de bu konuda uzman olabilirsiniz. Bu, dört yıllık tam zamanlı çalışmada kolayca yapılabilir.
Eric Lippert

32
@Anthony: Bunu yaptığımda insanlara derecemin aritmetik değil matematikte olduğunu söylüyorum .
Eric Lippert

7
Teoride, pratik ve teori aynıdır, ancak pratikte asla değildir.
İbrahim Hashimi

40

Parantezlerin varlığının program davranışı üzerinde etkili olabileceği önemli durumlar vardır:

1.

using System;

class A
{
    static void Foo(string x, Action<Action> y) { Console.WriteLine(1); }
    static void Foo(object x, Func<Func<int>, int> y) { Console.WriteLine(2); }

    static void Main()
    {
        Foo(null, x => x()); // Prints 1
        Foo(null, x => (x())); // Prints 2
    }
}

2.

using System;

class A
{
    public A Select(Func<A, A> f)
    {
        Console.WriteLine(1);
        return new A();
    }

    public A Where(Func<A, bool> f)
    {
        return new A();
    }

    static void Main()
    {
        object x;
        x = from y in new A() where true select (y); // Prints 1
        x = from y in new A() where true select y; // Prints nothing
    }
}

3.

using System;

class Program
{
    static void Main()
    {
        Bar(x => (x).Foo(), ""); // Prints 1
        Bar(x => ((x).Foo)(), ""); // Prints 2
    }

    static void Bar(Action<C<int>> x, string y) { Console.WriteLine(1); }
    static void Bar(Action<C<Action>> x, object y) { Console.WriteLine(2); }
}

static class B
{
    public static void Foo(this object x) { }
}

class C<T>
{
    public T Foo;
}

Umarım bunu pratikte asla görmezsiniz.


Soruma tam olarak bir cevap değil, ama yine de ilginç - teşekkürler.
chris

1
Burada 2'de neler olduğunu açıklayabilir misin?
Eric

2
Bu davranışın neden gerçekleştiğini ayrıntılı olarak açıklamalısınız.
Arturo Torres Sánchez


3

Bunun gibi soruları yanıtlamanın iyi bir yolu, Reflektör kullanmak ve hangi bilgi okunun üretildiğini görmektir. Derleyici optimizasyonları ve benzerleri hakkında derlemeleri yeniden derleyerek çok şey öğrenebilirsiniz.


6
Bu, belirli bir vaka için soruyu kesinlikle yanıtlayacaktır, ancak bu durumun tümünün temsilcisi olması gerekmez.
Beska

Katılmıyorum. Kişiye soruyu cevaplaması için bir yön verir.
Bryan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.