Announcement

Collapse
No announcement yet.

Mal wieder Grundlagen...?

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Mal wieder Grundlagen...?

    Warum gibt der folgende Ausdruck in C# einen anderen Wert als in C++ zurück?

    Code:
    x ^= y ^= x ^= y;
    Der Ausdruck kann auch geschrieben werden:

    Code:
    x = x ^ y = y ^ x = x ^ y;
    Was ich nicht verstehe ist folgendes:

    In C++ beginnt die Auswertung auf der rechten Seite und die Zwischenergebnisse werden gespeichert. Wenn die Auswertung beim ersten x links ankommt, hat x einen neuen Wert.

    In C# hingegen beginnt die Auswertung auf der linken Seite mit dem Einsetzen des Wertes für das erste x. Die nachfolgenden Ausdrücke werden dann mathematisch korrekt berechnet und als Wert des ersten y von links eingesetzt.

    Welches sind denn die Vorteile der Auswertung von links nach rechs, so wie diese in C# gemacht wird? Welche Überlegungen stecken dahinter?
    Zuletzt editiert von maro158; 28.02.2008, 14:16.

  • #2
    Hallo,

    Welche Überlegungen stecken dahinter?
    ich bin kein C++-Mann, so dass ich nur eine sehr allgemeine Antwort beisteuern kann. Das Grundprinzip von .NET besteht darin, für die Windows-Plattform ein sprachunabhängiges neues Fundament bereitzustellen (während im Gegensatz dazu Java auf dem Grundprinzip von einer einzigen Sprache für alle Plattformen basiert). Dieses Grundprinzip führt dazu, dass die Besonderheit einer bestimmten Sprache (wie C++) nur in Ausnahmenfällen auch in den .NET-Sprachen sichtbar werden sollte. Denn je mehr "Eigenheiten" im .NET-Framework auftauchen, umso eingeschränkter wird die Nutzung. Zum Beispiel kann ja eine in C# geschriebene Klasse in VB abgeleitet werden. Wenn dann die C#-Klasse zwei Methoden nur über die Groß-/Kleinschreibweise unterscheidet (was in C# zulässig ist), kommt die darauf zugreifende VB-Implementierung in tiefes Fahrwasser (weil es dort keine Unterscheidung der Schreibweise gibt).

    Comment


    • #3
      Hallo Andreas,

      vielen Dank für Deine Antwort.

      Originally posted by Andreas Kosch View Post
      Das Grundprinzip von .NET besteht darin, für die Windows-Plattform ein sprachunabhängiges neues Fundament bereitzustellen
      Damit bin ich einverstanden. Aber, soviel ich weiß, ist C++/CLI seit 2005 ECMA-standardisiert und unterstützt nebst nativen Funktionen alle CLR-Features, die C# und VB auch unterstützen. LINQ z.B. ist nicht nur für C# und VB.NET verfügbar, sondern allgemein für .NET, also auch für C++/CLI. Auch wenn C++/CLI-Code nicht immer über den JIT-er läuft, ist C++/CLI auch eine first class .NET-Sprache.

      Ich kann eine C++/CLI-DLL in einem C#-Projekt referenzieren und so eine Klasse in C# konsumieren, die in C++/CLI erstellt wurde. Ein Beispiel:

      Code:
      using System;
      using System.Collections.Generic;
      using System.Text;
      using System.Diagnostics;
      
      namespace XorAssignCs
      {
          class Program
          {
              static void Main(string[] args)
              {
                  int x, y;
                  Console.WriteLine("Calculating: x ^= y ^= x ^= y;");
      
                  x = 3;
                  y = 5;
      
                  x = MyXorTest.DoCalculateXorAssignment(x, y);
                  Console.WriteLine(String.Format("Result from C++: {0}", x));
      
                  x = 3;
                  y = 5;
      
                  x = MyXorTest.DoCalculateXorAssignmentCs(x, y);
                  Console.WriteLine(String.Format("Result from C#:  {0}", x));
      
                  Console.WriteLine("\nPress ENTER");
                  Console.ReadLine();
              }
      
      	// CXorText ist eine gemanagte Klasse und wird aus 
              // der C++/CLI-DLL XorAssign.dll importiert. Ihre Methode
              // DoCalculateXorAssignment führt die syntaktisch gleiche
              // Operation x ^= y ^= x ^= y durch. 
              private class MyXorTest : CXorTest
              {
                  public static int DoCalculateXorAssignmentCs(int x, int y)
                  {
                      return x ^= y ^= x ^= y;
                  }
              }
          }
      }
      Das obige C#-Programm gibt folgendes aus:

      Calculating: x ^= y ^= x ^= y;
      Result from C++: 5
      Result from C#: 0
      Die unspektakuläre C++/CLI-Klasse, deren Methode aufgerufen wird, sieht so aus:

      Code:
      #pragma once
      
      public ref class CXorTest
      {
      public:
      	CXorTest(void);
      	static System::Int32 DoCalculateXorAssignment(System::Int32 x, System::Int32 y)
      	{
      		x ^= y ^= x ^= y;
      		return x;
      	}
      };

      .NET != .NET ???

      Comment


      • #4
        Hallo,

        .NET != .NET ???
        so ist es, denn nur die Teile sind identisch, die zur Common Language Infrastructure-Specification (CLI) gehören:
        • Virtual Execution System VES (CLR)
        • Common Intermediate Language (CIL)
        • Common Language Specification (CLS)
        • Common Type System (CTS)

        Nicht ohne Grund muss sich eine .NET-Assembly nur dann vollständig an den gemeinsamen Teil halten, wenn die Assembly dies extra über das Attribut CLSCompliant(true) ankündigt.

        Wird CLSCompliant(true) jedoch nicht gesetzt, darf die Assembly alle Besonderheiten der eigenen Sprache vollständig ausreizen, ohne damit einen Regelverstoß zu begehen.

        Derartige Unterschiede gibt es sogar innerhalb der gleichen Sprache. Aus meinem Archiv stammt dabei das folgende Beispiel:
        "Aus historischen Gründen gibt es bei VB.NET den Sonderfall, dass die numerische Interpretation des Boolean-Wertes True nicht ganz eindeutig ist. Schauen wir uns zuerst das Beispiel in C# an – dort sorgt eine Typumwandlung über die Convert-Methode ToInt32 dafür, dass der Vergleich „iX < 20“ als Zahlenwert in die Berechnung einfließt. In VB.NET ist die Sache nicht ganz so eindeutig, denn dort wird beim Zugriff auf die VB.NET-spezifischen Funktionen wie zum Beispiel CInt für den Boolean-Wert True implizit der Integer-Wert -1 genutzt, während die Zugriffe der universellen (sprachunabhängigen) Methoden wie zum Beispiel Convert.ToInt32 implizit den Integer-Weg 1 verwenden.

        Code:
        Private Sub DoTest()
          Dim iX, iY As Integer
          iX = 10
          iY = iX + CInt(iX < 20)
          MessageBox.Show(iY.ToString(), "VB.NET")
        End Sub
           
        Private Sub DoTest()
          Dim iX, iY As Integer
          iX = 10
          iY = iX + Convert.ToInt32(iX < 20)
          MessageBox.Show(iY.ToString(), "VB.NET")
        End Sub
        
        private void DoTest()
        {
          int iX, iY;
          iX = 10;
          iY = iX + Convert.ToInt32(iX < 20);
          MessageBox.Show(iY.ToString(), "C#");
        }
        Zuletzt editiert von Andreas Kosch; 10.03.2008, 14:11.

        Comment


        • #5
          Vielen Dank für Deine Ausführungen! Jetzt dämmert mir langsam, dass die Unterschiede wohl viel tiefer zu suchen sind, als ich vermutet hatte. Die Datei AssemblyInfo.cpp enthält "[assembly:CLSCompliantAttribute(true)]", aber da die verwendeten Typen in diesem Fall gleich sind, werden auch keine Warnung ausgegeben, warum auch. Die beiden Compiler tun das, was ihnen von Haus aus beigebracht wurde, und heraus kommt das, was man in der römischen Rechtsprechung wohl am besten mit "non idem est si duo dicunt idem" umschrieben hätte.

          Comment

          Working...
          X