Web Log di Adrian Florea

"You know you've achieved perfection in design, not when you have nothing more to add, but when you have nothing more to take away." Antoine de Saint-Exupery
posts - 440, comments - 2715, trackbacks - 3944

My Links

Archives

Post Categories

Image Galleries

.RO Blogs

.RO People

.RO Sites

Blogs

Furls

Links

vinCitori

domenica 9 novembre 2008

Quando C# e' piuttosto l'eccezione che la regola

Il comportamento del compilatore C#, presentato prima qui da Diego e poi nel mio post precedente, sembra singolare tra gli altri compilatori piu' conosciuti .NET. Il seguente snippet C# entra in stack overflow:

using System;

class Foo {
    public virtual void Write(string s) {
        Console.WriteLine("Foo virtual " + s);
    }
}

class Bar : Foo {
    public override void Write(string s) {
        Console.WriteLine("Bar override " + s);
    }

    public void Write(string s, params string[] args) {
        Write("Bar overload " + s);
    }
}

class Program {
    static void Main() {
        Bar bar = new Bar();
        bar.Write("Ciao!"); // Process is terminated due to StackOverflowException
    }
}

mentre per gli altri linguaggi, stampa Bar override Ciao! Di seguito il codice equivalente in Visual Basic .NET, C++/CLI e Visual J#

Imports System

Class Foo
    Public Overridable Sub Write(ByVal s As String)
        Console.WriteLine("Foo virtual " + s)
    End Sub
End Class

Class
Bar : Inherits Foo
    Public Overrides Sub Write(ByVal s As String)
        Console.WriteLine("Bar override " + s)
    End Sub

    Public Overloads Sub
Write(ByVal s As String, ParamArray args As String())
        Write("Bar overload " + s)
    End Sub
End Class

Module
Program
    Sub Main
        Dim bar As Bar = New Bar
        bar.Write("Ciao") ' stampa Bar override Ciao!
    End Sub
End Module

using namespace System;

ref class Foo {
    public:
    virtual void Write(String^ s) {
        Console::WriteLine("Foo virtual " + s);
    }
};

ref class Bar : Foo {
    public:
    virtual void Write(String^ s) override {
        Console::WriteLine("Bar override " + s);
    }

    void Write(String^ s, ... array<String^>^ args) {
        Write("Bar overload " + s);
    }
};

int main() {
    Bar^ bar = gcnew Bar;
    bar->Write("Ciao!"); // stampa Bar override Ciao!
};

import System.*;

class Foo {
    public void Write(String s) {
        Console.WriteLine("Foo virtual " + s);
    }
}

class Bar extends Foo {
    public void Write(String s) {
        Console.WriteLine("Bar override " + s);
    }
    public void Write(String s, /** @attribute ParamArray() */ String[] args) {
        Write("Bar overload " + s);
    }
}

class Program {
    public static void main(String[] args) {
        Bar bar = new Bar();
        bar.Write("Ciao"); // stampa Bar override Ciao!
    }
}

Ho sempre considerato C# come linguaggio "centrale" di .NET, una chiave per capire meglio lo spirito della piattaforma - percio' mi meraviglio quando trovo comportamenti in C# che sono piuttosto l'eccezione anziche' la regola rispetto agli altri linguaggi .NET. A voi quale comportamento sembra piu' corretto/intuitivo?

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (225) | Filed Under [ Quiz Sharp Carillon .NET Bugs? ]

Quiz Sharp #71 [override/overload]

Questo post di Diego Martelli, fattomi notare da un amico, riesce secondo me a sorprendere un comportamento interessante di C#, ovvero il seguente snippet di codice entra in stack overflow:

using System;

class Foo {
    public virtual void Write(string s) {
        Console.WriteLine("Foo virtual " + s);
    }
}

class Bar : Foo {
    public override void Write(string s) {
        Console.WriteLine("Bar override " + s);
    }

    public void Write(string s, params string[] args) {
        Write("Bar overload " + s);
    }
}

class Program {
    static void Main() {
        Bar bar = new Bar();
        bar.Write("Ciao!");
    }
}

Probabilmente molti si aspetterebbero che venisse stampato "Bar override Ciao!" a console e invece il metodo chiamato e' il Write con l'elenco variabile di parametri e non il metodo in override. Questo comportamento e' dovuto, secondo me, al fatto che abbiamo istanziato bar come:

Bar bar = new Bar();

e non come:

Foo bar = new Bar();

Il metodo Write in override nella classe Bar non fa altro che specializzare il metodo virtuale della classe base Foo, percio' perde nella gara dei metodi in overload della classe Bar perche' Write nella sua forma espansa (ECMA-334, 14.4.2.1) ha un parametro di tipo string e zero elementi nell'array di parametri.

Detto questo, ecco il mio quiz: Cosa stampa questo snippet a console?

using System;

class Foo {
    public override string ToString() {
        return "override ";
    }
    public string ToString(params string[] args) {
        return "overload ";
    }
}

class Program {
    static void Main() {
        Foo foo = new Foo();
        Console.Write(foo);
        Console.WriteLine(foo.ToString());
    }
}

 

  • A: override override
  • B: override overload
  • C: overload overload

 

:-)

posted @ lunedì 1 gennaio 0001 00:00 | Feedback (311) | Filed Under [ Quiz Sharp Carillon .NET ]

Powered by:
Powered By Subtext Powered By ASP.NET