Rounding in C# (and PHP)
Rundung erscheint auf den ersten Blick so selbstverständlich, dass so mancher geneigt scheint, sich darüber gar keine großen Gedanken zu machen. Beim Ab- und Aufrunden mit Methoden wie
Sowohl bei C# als auch bei PHP lässt sich dieses Verhalten jedoch manuell anpassen (und dadurch nötigenfalls angleichen), indem man unter C# einen Wert der Enumeration
Math.Floor
und Math.Ceiling
gibt es auch tatsächlich keine großen Überraschungen bei den meisten Programmiersprachen:
Auf- und Abrunden
Spannend wird es jedoch beim allgemeineren Rundungsverfahren mit 010203040506070809
// Abrundungdouble floor1 = Math.Floor(1.3); // 1double floor2 = Math.Floor(1.5); // 1double floor3 = Math.Floor(1.7); // 1 // Aufrundungdouble ceiling1 = Math.Ceiling(1.3); // 2double ceiling2 = Math.Ceiling(1.5); // 2double ceiling3 = Math.Ceiling(1.7); // 2
Math.Round
, bei welchem sich das Verhalten standardmäßig zu dem unterscheiden kann, was man beispielsweise aus der Schule als kaufmännisches Runden oder vom Standardverhalten von round
aus PHP kennt. Der Unterschied liegt konkret beim Rundungsverhalten an der Ziffer 5
:
Rundungsverhalten an der Ziffer "5"
Die Ursache für dieses für manche möglicherweise überraschende Verhalten liegt darin begründet, dass bei C# das mathematische Rundungsverfahren zur Anwendung kommt, welches in so einem Fall standardmäßig die Rundung zur nächsten geraden Ziffer vorschreibt, anstatt pauschal aufzurunden. Das Anliegen dabei ist es, statistische Verzerrungen durch ausschließliches Aufrunden an dieser Stelle zu vermeiden. Dies ist in jedem Fall bei der Interoperabilität mit anderen Systemen, die auf eine gleiche Datenbasis zugreifen, zu berücksichtigen.01020304050607
double rounded11 = Math.Round(2.3); // 2double rounded12 = Math.Round(2.5); // 2 (!)double rounded13 = Math.Round(2.7); // 3
double rounded21 = Math.Round(7.3); // 7double rounded22 = Math.Round(7.5); // 8double rounded23 = Math.Round(7.7); // 8
Sowohl bei C# als auch bei PHP lässt sich dieses Verhalten jedoch manuell anpassen (und dadurch nötigenfalls angleichen), indem man unter C# einen Wert der Enumeration
MidpointRounding
oder unter PHP eine der Konstanten PHP_ROUND_HALF_*
an die entsprechende Methode/Funktion zur Rundung übergibt. Move WPF Windows without Title Bar
Ein WPF-Fenster, dessen Eigenschaft
Eine häufig gewünschte und auch meist sehr sinnvolle Funktionalität ist jedoch, dass der Benutzer das Fenster dennoch verschieben können soll. Dies ist – wie so oft, wenn man weiß, wie – sehr einfach zu lösen. Wir registrieren dazu einfach eine Ereignisbehandlung für
WindowStyle
der Wert None
zugewiesen ist, besitzt keine standardmäßige Titelleiste mehr – was ja letztlich auch Sinn der Sache ist.Eine häufig gewünschte und auch meist sehr sinnvolle Funktionalität ist jedoch, dass der Benutzer das Fenster dennoch verschieben können soll. Dies ist – wie so oft, wenn man weiß, wie – sehr einfach zu lösen. Wir registrieren dazu einfach eine Ereignisbehandlung für
MouseLeftButtonDown
auf einem Steuerelement des Fensters (oder im Zweifelsfall gar auf dem Fenster selbst) und rufen die DragMove
-Methode des Fensters auf:
Schon lässt sich das Fenster wie gewohnt bei gedrückter linker Maustaste verschieben. Attributes in C#
Attribute in C# sind eine komfortable Möglichkeit, um Klassen, Methoden und andere Member mit Metadaten anzureichern. Diese können anschließend während der Laufzeit per Reflexion ausgewertet werden.
Konkret möchten wir ein Attribut
Nun setzen wir das Attribut für die Methode
Konkret möchten wir ein Attribut
Description
erzeugen, mit welchem wir Methoden eine Beschreibung geben können. Wir müssen uns dazu lediglich eine von Attribute
abgeleitete Klasse erstellen, die die entsprechende Information aufnehmen kann:
"Description"-Attribut definieren
Über das 0102030405060708091011
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]public class Description : Attribute { public string Text { get; set; }
public Description(string text) { this.Text = text; }}
AttributeUsage
-Attribut legen wir dabei fest, dass das Attribut lediglich (einmal) für eine Methode Verwendung finden können soll.Nun setzen wir das Attribut für die Methode
StartImportantAction
einer Klasse ImportantClass
:
"Description"-Attribut setzen
Anschließend können wir jederzeit von anderer Stelle aus auf diese Information zugreifen:
0102030405060708
public class ImportantClass { [Description("Führt eine wichtige Aktion aus!")] public void StartImportantAction() { /** * Aktion ausführen **/ }}
"Description"-Attribut abrufen
Auf ähnliche Art und Weise entsteht beispielsweise automatisch die Schnittstellenbeschreibung von BitStadt.de. Im MSDN findet sich auch eine Übersicht allgemeiner Attribute des .NET-Frameworks. 0102030405060708
// MethodInfo ermittelnMethodInfo methodInfo = typeof(ImportantClass).GetMethod("StartImportantAction");
// "Description"-Attribut ermittelnDescription description = methodInfo.GetCustomAttribute<Description>();
// Beschreibung auslesenstring text = description.Text; // "Führt eine wichtige Aktion aus!"
HttpHandler in ASP.NET MVC
Manchmal kann es sinnvoll sein, bestimmte Aufrufe einer Webanwendung abseits der "normalen" Vorgehensweise zu behandeln. Konkret soll es darum gehen, Aufrufe mit der Dateiendung "
Ein bekanntes – und weitaus mächtigeres – Projekt, welches von dieser Möglichkeit Gebrauch macht, ist dotless, eine Implementierung der Stylesheet-Skriptsprache LESS für .NET. Diese ermöglicht u. a. eine übersichtlichere Verschachtelung, Variablen und Funktionen in Stylesheets, wobei der HttpHandler dafür sorgt, dass die vom Browser angeforderten
Die Verwendung der MVC-Erweiterung für ASP.NET ist für dieses Vorgehen übrigens nicht unbedingt erforderlich, ich arbeite jedoch nahezu ausschließlich mit dieser.
.css
" abzufangen, um in den statischen Dateien Platzhalter dynamisch zu ersetzen, was mit CSS selbst nicht möglich wäre. Unser Stylesheet:
Site.css
Die Umsetzung ist sehr einfach, wir müssen dazu lediglich eine Klasse erstellen, welche die Schnittstelle 01020304
body { background-color: #{backgroundColor}; color: #{color};}
IHttpHandler
und natürlich auch das gewünschte Verhalten implementiert – der Fantasie sind hier kaum Grenzen gesetzt. Wir belassen es der Einfachheit wegen bei einem einfachen (und nicht sehr effizienten) Beispiel:
HttpHandler implementieren
Abschließend passen wir die Konfiguration (→ 010203040506070809101112131415161718192021222324
public class HttpHandler : IHttpHandler { public bool IsReusable { get { return true; } }
public void ProcessRequest(HttpContext context) { // Ersetzungsdaten (in der Praxis evtl. aus Datenbank) Dictionary<string, string> replacementData = new Dictionary<string, string>() { {"backgroundColor", "000"}, {"color", "fff"} };
// Platzhalter im Stylesheet mit Ersetzungsdaten austauschen StringBuilder css = new StringBuilder(File.ReadAllText("Site.css"));
foreach(KeyValuePair<string, string> replacement in replacementData) { css.Replace(String.Format("{{0}}", replacement.Key), replacement.Value); }
context.Response.Write(css.ToString()); }}
Web.config
) an, um unsere eigene Behandlung zu registrieren:
Konfiguration erweitern
Weiterführende Informationen zum Thema finden sich im MSDN.01020304050607
<configuration> <system.webServer> <handlers> <add name="DynamicStylesheet" path="*.css" type="HttpHandler" verb="GET" /> </handlers> </system.webServer></configuration>
Ein bekanntes – und weitaus mächtigeres – Projekt, welches von dieser Möglichkeit Gebrauch macht, ist dotless, eine Implementierung der Stylesheet-Skriptsprache LESS für .NET. Diese ermöglicht u. a. eine übersichtlichere Verschachtelung, Variablen und Funktionen in Stylesheets, wobei der HttpHandler dafür sorgt, dass die vom Browser angeforderten
.less
-Dateien serverseitig in "reines" CSS umgewandelt und ausgeliefert werden.Die Verwendung der MVC-Erweiterung für ASP.NET ist für dieses Vorgehen übrigens nicht unbedingt erforderlich, ich arbeite jedoch nahezu ausschließlich mit dieser.
Hashing in C# und PHP
Den meisten PHP-Entwicklern sind die beiden Funktionen
Diesen Klassen kann man über die
Die Rückgabe dieser Methode dürfte nun jedoch leider noch gar nicht dem entsprechen, was viele erwarten – die hexadezimale Schreibweise wie in PHP, so dass diese Ausgaben insbesondere nicht kompatibel zueinander für Vergleiche sind, was die Interoperabilität natürlich massiv beeinträchtigt. C# liefert standardmäßig nämlich das, was bei den entsprechenden PHP-Funktionen mit dem Parameter
Da die hexadezimale Darstellung jedoch tatsächlich häufig praktikabler ist, stützen wir uns ausnahmsweise (
) auf diese Vorgehensweise und bringen C# zu diesem – unter anderem von PHP gewohnten – Verhalten:
md5(…)
und sha1(…)
geläufig. Diese liefern zu einer übergebenen Zeichenkette einen Streuwert ("Hash") in hexadezimaler Darstellung. Zu diesem Zweck gibt es in C# die beiden Klassen MD5CryptoServiceProvider
und SHA1CryptoServiceProvider
.Diesen Klassen kann man über die
ComputeHash
-Methode unter anderem ein byte
-Array übergeben und bekommt daraufhin ein solches zurück, welches den Hash darstellt. Da wir es in der Praxis aber doch meist einfach nur mit Zeichenketten und u. U. auch mit verschiedenen Hash-Algorithmen (z. B. MD5, SHA1) zu tun haben, möchten wir das Ganze in eine komfortable generische Erweiterungsmethode für Zeichenketten verpacken:
Methode implementieren
Für diejenigen, denen die Arbeit mit generischen Typen (noch) nicht geläufig ist, werde ich in Kürze auch noch einen etwas ausführlicheren Beitrag zu diesem Thema verfassen.0102030405060708
public static string GetHash<T>(this string str) where T : HashAlgorithm, new() { using(T hashProvider = new T()) { // Streuwert berechnen byte[] hash = hashProvider.ComputeHash(Encoding.UTF8.GetBytes(str));
return Encoding.UTF8.GetString(hash); }}
Die Rückgabe dieser Methode dürfte nun jedoch leider noch gar nicht dem entsprechen, was viele erwarten – die hexadezimale Schreibweise wie in PHP, so dass diese Ausgaben insbesondere nicht kompatibel zueinander für Vergleiche sind, was die Interoperabilität natürlich massiv beeinträchtigt. C# liefert standardmäßig nämlich das, was bei den entsprechenden PHP-Funktionen mit dem Parameter
$raw_output
erhältlich ist.Da die hexadezimale Darstellung jedoch tatsächlich häufig praktikabler ist, stützen wir uns ausnahmsweise (

Methode implementieren (hexadezimale Rückgabe)
Jetzt liefert unsere Erweiterungsmethode für C# exakt das gleiche Ergebnis wie PHP das standardmäßig macht und kann darüber hinaus besonders einfach und flexibel auf jeder Zeichenkette verwendet werden:
Durch Übergabe der gewünschten Implementierung als Typparameter erhalten wir nun direkt das Ergebnis. 0102030405060708
public static string GetHash<T>(this string str) where T : HashAlgorithm, new() { using(T hashProvider = new T()) { // Streuwert berechnen byte[] hash = hashProvider.ComputeHash(Encoding.UTF8.GetBytes(str));
return BitConverter.ToString(hash).Replace("-", String.Empty).ToLower(); }}
Project links
-
BitStadt – Stadtportal
Berlin · Hamburg · Amsterdam -
CCC – Fahrplan
Schedules for the CCCongress
Categories / Archive | Übersicht
- PHP functions in C# (136)
- Dictionary (257)
Tags
.NET · ADO.NET · Work · ASP.NET MVC · Blog · C# · Generics · Society · Computer Science · Java · LINQ · Logic · Mathematics · Network · PHP · Project · Security · Software development · Studies · Technics · Theory · Web design · WPF