Donnerstag, 30. September 2010

Auflösung des Rätsels

In einem vorigen Post gab es ein kleines Programmierrätsel. Hier jetzt die Auflösung:
Das gesuchte "Gerät" aus dem Rätsel ist ein Volladdierer.
Ein Volladdierer ist ein Schaltznetz, mit dem sich 3 Binärzahlen addieren lassen.
Folglich hat die Schaltung 3 Eingänge für die 3 zu addierenden Zahlen und 2 Ausgänge, s und c.
Der Ausgang s (engl. sum = Summe) liefert die niederwertige Stelle des Ergebnisses, der Ausgang c (engl. carry = Übertrag) die höherwertige.
Genauere Informationen und die Wahrheitstabelle (in diesem Fall die Ergebnisse der Additionen abhängig von den Eingabewerten) entnehme man Wikipedia.
In der Codeklasse aus dem Rätsel wird die Berechnung durch Aufruf der Methode ABC() angeregt. Diese erwartet 3 Strings als Parameter, welche die zu addierenden Binärzahlen darstellen.
Der Buchstabe "x" steht hierbei für die Ziffer 0, der Buchstabe "y" für 1. Zuerst wird nun die Methode DEF() aufgerufen, in welcher auf verschiedene Arten geprüft wird, ob wirklich nur "x" und "y" als Eingabe übergeben wurde.
Wurde eine ungültige Eingabe übergeben, gibt das Programm "d" stellvertretend für Fehler zurück.
In ABC() wird andernfalls die Summe der 3 Zahlen berechnet und das Ergebnis als String zurückgegeben.
Die linke Stelle des Ergebnisstrings ist die niederwertige Stelle der Summe (s), die rechte Stelle die höherwertige (c).
Beim Ergebnis steht nun der Buchstabe "a" für eine 0 und der Buchstabe "b" für eine 1.

Danke an alle für's Mitmachen und Mitraten!

Mittwoch, 29. September 2010

Computer - Klasse aus Microsoft.VisualBasic.Devices

Im Namespace Microsoft.VisualBasic.Devices gibt es die Klasse Computer, die einige interessante Methoden bietet. Die meisten werden sich wohl über "Standard" C# - Code realisieren lassen, trotzdem möchte ich diese Klasse aus Neugierde einmal näher betrachten.
Um die Klasse nutzen zu können, muss ein Verweis auf Microsoft.VisualBasic (Projekt - Verweis hinzufügen, Reiter .Net) eingebunden werden sowie Microsoft.VisualBasic.Devices mittels using eingebunden werden.
Die Computer Klasse kann nun zur Manipulation von Objekten, die den eigenen Computer betreffen, verwendet werden, Einsatzbereiche sind u.a. Audio, Tastatur, Maus und Ports.
Hier ein paar Beispiele, was man damit so alles anfangen kann:

Abspielen von .wav - Dateien (die "C# - Variante" wurde in diesem Post beschrieben):

// using Microsoft.VisualBasic; muss für dieses Beispiel ebenfalls eingebunden werden!
Computer computer = new Computer();
computer.Audio.Play("pfad zur .wav - Datei", AudioPlayMode.Background);

Die Methode Play() erwartet als ersten Parameter den Pfad zur abzuspielenden Datei und als zweiten den Abspielmodus.
Der hier benutzte Modus spielt den Sound im Hintergrund ab während das Programm weiterläuft.
Außerdem gibt es die Modi WaitToComplete (das Programm wartet auf die Beendigung das Sounds) und BackgroundLoop (der Sound wird wiederholt während das Programm weiterläuft).

Aktuelle Zeit und aktuelles Datum abfragen (als Alternative siehe dieser Post ganz unten):

Computer ThisComputer = new Computer();
MessageBox.Show(ThisComputer.Clock.LocalTime.ToString());

Größe des Arbeitsspeichers herausfinden:

Computer ThisComputer = new Computer();
ulong RAMSize = ThisComputer.Info.TotalPhysicalMemory;

Dienstag, 28. September 2010

Ton von Mikrofon aufzeichnen

Im heutigen Post geht es um die Soundaufnahme mit einem Mikrofon. Hierfür benötigen wir in C# die WinAPI - Funktion mciSendString().
Das Media Control Interface (MCI) ist eine Schnittstelle, die Befehle zum Abspielen und Aufnehmen von Multimediadaten zur Verfügung stellt. Über vorher genannte Funktion können diese Befehle an den Computer gesendet und somit verarbeitet werden.
Die Funktion mciSendString() befindet sich in der Datei winmm.dll und kann folgendermaßen eingebunden werden (zum Einbinden von externen Bibliotheken ist folgende using - Anweisung nötig: using System.Runtime.InteropServices):

[DllImport("winmm.dll")]
private static extern int mciSendString(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);

Die Parameter haben folgende Bedeutung:
  • lpstrCommand: zu sendender MCI - Befehl
  • lpstrReturnString: falls erforderlich, Buffer der Rückgabeinformationen empfängt
  • uReturnLength: Größe des im vorigen Parameter beschriebenen Buffers
  • hwndCallback: Handle zum Fenster, das bei Rücksprung benachrichtigt werden soll

Wir brauchen zur Steuerung des Mikrofons nur den 1. Parameter und übergeben als restliche "" bzw 0.
Zum Starten der Aufnahme müssen wir dann die beiden Befehle "open new Type waveaudio Alias recsound" und "record recsound" senden, zum Stoppen "save recsound " und "close recsound".
Und so könnte der Code einer Windows Forms-Anwendung aussehen, die über 2 Buttons verfügt, über welche die Soundaufnahme gestartet bzw. gestoppt wird:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        [DllImport("winmm.dll")]
        private static extern int mciSendString(string lpstrCommand, string lpstrReturnString, int uReturnLength, int hwndCallback);

        public Form1()
        {
            InitializeComponent();
        }

        // Starten der Aufnahme
        private void button1_Click(object sender, EventArgs e)
        {
            mciSendString("open new Type waveaudio Alias recsound", "", 0, 0);
            mciSendString("record recsound", "", 0, 0);
        }

        // Stoppen der Aufnahme
        private void button2_Click(object sender, EventArgs e)
        {
            mciSendString("save recsound C:\\records\\record1.wav", "", 0, 0);
            mciSendString("close recsound", "", 0, 0);
        }

    }
}

Montag, 27. September 2010

Rätsel: Was macht dieses Programm?

Anlässlich des 100. Posts habe ich ein kleines Rätsel vorbereitet.
Die vorgestellte Klasse beschreibt die Funktion eines "Geräts" aus der technischen Informatik, wer dieses zuerst errät, hat gewonnen ;-)
Die Klasse ist absichtlich etwas unübersichtlich programmiert, bei Benutzung dieser wird die Methode ABC() mit 3 Parametern aufgerufen.
Und hier nun der Code:

    public class CrazyTool
    {
        public string ABC(string a, string b, string c)
        {
            if (!DEF(a, b, c))
                return "d";

            if (a == "x")
            {
                int d = 0;
                if (b == "x")
                    d = 0;
                else
                    d = 1;
                int e = d + int.Parse(c.Replace('x', '0').Replace('y', '1'));
                switch (e * 3)
                {  
                    case 0: return ("aa");
                    case 3: return ("ba");
                    case 6: return ("ab");
                }
            }
            else
            {
                int f = 0;
                if (b == "x")
                    f = 0;
                else
                    f = 1;
                int g = f + int.Parse(c.Replace('x', '0').Replace('y', '1'));
                switch (g * 3)
                {  
                    case 0: return ("ba");
                    case 3: return ("ab");
                    case 6: return ("bb");
                }
            }

            return "d";
        }

        private bool DEF(string a, string b, string c)
        {
            if (a != "x" && a != "y")
                return false;
            if (((byte)(b.ToCharArray()[0]) != 120 && ((byte)(b.ToCharArray()[0]) != 121)))
                return false;
            Regex r = new Regex("[xy]");
            if (!r.IsMatch(c))
                return false;
            return true;
        }
    }

Samstag, 25. September 2010

Anzahl der Monitore herausfinden

Die Anzahl der an den PC angeschlossenen Monitore lässt sich über verschiedene Varianten auslesen, eine führt über die Klasse SystemInformation:

int MonitorsCount = SystemInformation.MonitorCount;

Freitag, 24. September 2010

Header Daten einer HTML Seite auslesen

Die Klassen WebRequest und WebResponse stellen gewissermaßen einen erweiterten WebClient dar, sie können dazu benutzt werden, um über das HTTP Protokoll Anfragen an bestimmte Seiten zu senden und Antworten auszulesen.
Unter anderem können damit auch sehr leicht die Header Elemente einer HTML Seite ausgelesen werden.
Das folgende Beispiel sollte eigentlich selbsterklärend sein, es ist eine Konsolenanwendung, die die Header Daten von diesem Blog ausliest (using System.Net vorrausgesetzt):

        static void Main(string[] args)
        {
            WebRequest HeaderRequest = HttpWebRequest.Create("http://csharp-tricks.blogspot.com/");
            WebResponse HeaderResponse = HeaderRequest.GetResponse();

            foreach (string HeaderKey in HeaderResponse.Headers)
            {
                Console.WriteLine(HeaderKey + ": " + HeaderResponse.Headers[HeaderKey]);
            }
        }

Das Ergebnis sieht folgendermaßen aus:

X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Transfer-Encoding: chunked
Cache-Control: private
Content-Type: text/html; charset=UTF-8
Date: Fri, 24 Sep 2010 18:33:03 GMT
Expires: Fri, 24 Sep 2010 18:33:03 GMT
ETag: "fb52caee-c1f0-4f4a-8caa-de7e4de4dfaa"
Last-Modified: Fri, 24 Sep 2010 18:31:27 GMT
Set-Cookie: blogger_TID=9919beb7f2e6b1c8; Domain=.blogger.com; HttpOnly
Server: GSE

Mittwoch, 22. September 2010

Dateien aus dem Internet herunterladen

Das Herunterladen von Dateien aus dem Internet erfolgt auf die gleiche Weise wie das wie im vorigen Post beschriebene Auslesen des Quelltexts von Webseiten.
Wir benutzten also wieder die Klasse WebClient und von dieser die Methode DownloadFile().
Zwischen dem Herunterladen des Quelltexts und dem Herunterladen von Dateien besteht auch gar kein Unterschied, die Methode DownloadFile() des WebClients lädt in beiden Fällen nämlich die angegebene Ressource herunter, in einem Fall die Datei, auf die explizit verlinkt wurde (z.B. http://www.meinedomain.de/meinedatei.exe), im anderen Fall einfach das komplette HTML - Dokument, also den Quellcode (z.B. http://www.meinedomain.de/).
Um nun aber, wie der Titel schon aussagt, eine bestimmte Datei aus dem Internet zu downloaden, rufen wir die Funktion DownloadFile() mit dem direkten Link zur Datei als 1. Parameter und dem lokalen Pfad am PC, in den die Datei gespeichert werden soll, als 2. Parameter, auf.
Das folgende Beispiel lädt den von mir programmieren Matrix - Bildschirmschoner herunter (System.Net muss eingebunden sein):
WebClient Webclient1 = new WebClient();
Webclient1.DownloadFile("http://205.196.122.15/o09zbpz46rjg/jig1jyyizx0/MatrixSaver.scr", @"C:\Users\User\Downloads\MatrixSaver.scr");

Diese Methode blockiert das Programm nun aber solange, bis die Datei nicht vollständig heruntergeladen wurde. Um den Mainthread weiter laufenzulassen und die Datei asynchron herunterzuladen, kann die Methode DownloadFileAsync() verwendet werden.
Vorher wäre es hilfreich, noch 1 oder 2 Events zu deklarieren, um dem Programm den Status des Downloads mitzuteilen.
Events sind Ereignisse, wie z.B. der Klick auf einen Button, legt man hinter diese eine Methode, wird die Methode aufgerufen, wenn das Ereignis eintritt.
Wir können zum asynchronen File Download 2 Events benutzen, die, wie gesagt, optional sind:
DownloadFileCompleted tritt ein, wenn der Download beendet wurde (kann auch durch einen Fehler auftreten!), DownloadProgressChanged, wenn sich der Fortschritt des Downloads geändert hat.
Methoden zur Behandlung der Ereignisse können über den Operator + hinzugefügt werden, für DownloadFileCompleted beispielsweise so:
DownloadFileCompleted += new AsyncCompletedEventHandler(zielmethode).
zielmethode benötigt nun nur noch die richtige Signatur, d.h. den richtigen Rückgabetyp und die richtigen Parameter, in diesem Fall folgende:
private void zielmethode(object sender, AsyncCompletedEventArgs e).
Das folgende Beispielprogramm startet beim Laden des Formulars das Herunterladen der Internet Explorer 9 Beta (ca. 20 MB) von Microsoft, bei Beendigung des Downloads wird das Ergebnis mit einer MessageBox ausgegeben, der Status des Downloads wird in einer ProgressBar angezeigt, ein entsprechendes Objekt mit dem Namen progressBar1 muss sich auf dem Formular befinden, außerdem muss System.Net mittels using eingebunden sein:

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                WebClient Webclient1 = new WebClient();
                Webclient1.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
                Webclient1.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadStatusChanged);
                Webclient1.DownloadFileAsync(new Uri("http://download.microsoft.com/download/B/4/8/B48BF620-EBF5-4683-8674-A878C5ADB595/IE9-Windows7-x86-deu.exe"), @"C:\Users\User\Downloads\ie9.exe");
            }
            catch (Exception ex)    
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
        {
            // prüfen, ob der Download mit oder ohne Fehler beendet wurde
            if (e.Error == null)
                MessageBox.Show("Download fertig.");
            else
                MessageBox.Show("Download fehlerhaft: " + e.Error);
        }

        private void DownloadStatusChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            // Prozentualen Fortschritt in progressBar1 anzeigen
            progressBar1.Value = e.ProgressPercentage;
        }

Dienstag, 21. September 2010

HTML Quelltext einer Webseite auslesen

Der HTML Quellcode einer Internetseite lässt sich mit der Klasse WebClient auslesen. Diese stellt verschiedene Methoden zum Senden und Empfangen von Internetressourcen bereit und befindet sich im Namespace System.Net, using System.Net wird also vorrausgesetzt.
Zum Auslesen des Quellcodes können 2 Methoden verwendet werden, DownloadString(string url) und DownloadFile(string url, string filename).
Erstere lädt den Quelltext von der angegebenen Adresse herunter und gibt diesen als String zurück, zweitere speichert den HTML Code in der angegebenen Datei.
Folgendes Beispiel liest den Quelltext des RSS - Feed dieses Blogs aus:

WebClient Webclient1 = new WebClient();
string SourceCode = Webclient1.DownloadString("http://csharp-tricks.blogspot.com/feeds/posts/default?orderby=updated");

In manchen Fällen muss zur richtigen Anzeige die Kodierung geändert werden.
Der WebClient lädt die angeforderte Ressource in byte - Arrays herunter, diese werden dann mit einer bestimmten Kodierung (die häufigste ist zum Beispiel UTF-8) in eine Zeichenfolge konvertiert.
Um die Codierung zu ändern, muss vor dem Downloaden die Eigenschaft Encoding der Klasse WebClient geändert werden.

Sonntag, 19. September 2010

CLR - Version herausfinden

Die Versionen des .Net Frameworks unterscheiden sich teilweise deutlich in ihrer Funktionalität, die aktuelle Version 4 bietet einige Features mehr als Version 1.
Kernkomponente des .Net Frameworks ist die sogenannte Common Language Runtime (CLR), die Laufzeitumgebung, in der Programme laufen.
Um diese Versionsnummer abzufragen, ist die Klasse System.Environment.Version nötig.
Folgende Codezeile liest die installierte Version der CLR aus, in der das Programm läuft:

string CLRVersion = System.Environment.Version.ToString();

Allerdings ist die Version der Common Language Runtime nicht mit der Versionsnummer des .Net Frameworks identisch!
Die .Net Versionen 1.0 und 1.1 benutzen die CLR Version 1.0, das .Net Framework 2.0, 3.0 und 3.5 die Version 2.0 und das aktuelle .Net Framework 4.0 benutzt CLR 4.0.

Dienstag, 14. September 2010

Emails empfangen

Hinweis: Dieser Post erklärt die Grundlagen des Empfangens von Emails. Zur Zeit des Posts war dies noch ohne SSL möglich, heutzutage ist dies jedoch meist Voraussetzung. Daher erkläre ich das Empfangen von Emails unter Benutzung einer SSL - Verbindung in diesem neuen Post. Dort wird auch die Verwendung eines IMAP - Servers beschrieben - in diesem Post wird nur auf einen POP3 - Server eingegangen.

In einem vorigen Post habe ich gezeigt, wie man mit C# Emails senden kann.
Heute geht es um das Empfangen von Emails.
Das Senden war ganz einfach, da .Net vordefinierte Methoden zum Verbinden mit einem SMTP - Server zur Verfügung stellt, über den die Emails gesendet werden können.
Zum Empfangen muss man etwas tiefer in die Trickkiste greifen, das Programm muss sich am Posteingangsserver anmelden und die richtigen Befehle zum Abholen und Lesen von Mails senden.
Clients können sich Emails vom Mailserver über das POP3 - oder das IMAP - Protokoll abholen. IMAP bietet mehr Funktionen, die meisten kostenlosen Mailanbieter wie WEB oder GMX verwenden aber das POP3 - Protokoll.
Der hier gezeigte Code arbeitet mit dem POP3 - Protkoll.
Ein POP3 - Server wartet auf einem bestimmten Port (meist 110) auf Anfragen. Ein Client kann sich mit einem Benutzernamen und Passwort dort anmelden und dann Befehle senden, die alle per Zeilenumbruch getrennt sein müssen.
Der Server schickt auf jeden Befehl eine Antwort und erwartet ggf. Eingaben.
Den POP3 - Server realisieren wir in C# mit einem TcpClient und senden die Befehle über einen NetworkStream.
Bevor ich näher auf den Code eingehe, erkläre ich kurz den grundlegenden Ablauf der Kommunikation mit dem Posteingangsserver:

Montag, 13. September 2010

Unterschied Funktionen / Prozeduren / Methoden

In vorigen Posts habe ich bis jetzt immer von "Funktionen" im Zusammenhang mit C# gesprochen wenn es um wiederverwendbare Codefragmente ging, denen Parameter übergeben werden können und die teilweise einen Rückgabewert haben.
In der Programmierung gibt es hierfür die Begriffe Prozedur, Funktion und Methode , die teilweise synonym verwendet werden aber doch gewisse Merkmale besitzen.
Von "Funktion" bei C# zu sprechen, war wahrscheinlich nicht ganz korrekt, deswegen werde ich im Folgenden den Begriff "Methode" verwenden und dies auch bei den älteren Posts korrigieren.
Denn:
Methode kann als Oberbegriff für die Begriffe Funktion und Prozedur betrachtet werden. Eine Prozedur ist dann eine Methode ohne Rückgabewert und eine Funktion eine Methode mit Rückgabewert.
Weiterhin gibt es in der funktionalen Programmierung insofern eine Unterscheidung zwischen Prozeduren / Funktionen und Methoden, als dass Prozeduren (oder eben Funktionen) als freie Methoden gelten und Methoden direkt an ein bestimmtes Objekt gebunden sind.
In der objektorientierten Programmierung allgemein und vor allem bei .Net lässt man diese Unterscheidungen meist fallen und benutzt stattdessen nur den Oberbegriff der Methode.
Diese Benennung ist nachvollziehbar, da nicht mehr zwischen Methoden mit und ohne Rückgabewert unterschieden wird, letzere geben einfach einen leeren Typ zurück (in C# werden sie mit void gekennzeichnet).
Außerdem haben bei der objektorientierten Programmierung alle Methoden einen Bezug zu einem Objekt, es gibt also keine Methoden mehr, die kontextfrei "mittem im Quellcode stehen".

Freitag, 10. September 2010

C# Syntax Highlighter für HTML Version 2

Ich habe nun das Programm, mit dem ich die hier gezeigten Codebeispiele aus dem C# Editor in HTML - Form bringe, überarbeitet.
Eine Erklärung, was das Programm genau macht und wie es funktioniert, gibt es im Post mit der alten Version des Prorgamms.
Hier werde ich nur kurz den Quellcode neu posten, der im Grundgerüst gleich geblieben ist und nur an einigen Stellen verändert und verbessert wurde.
Die neuen Funktionen umfassen unter anderem das Syntax - Highlighting von Klassen sowie eine verbesserte Erkennung von Kommentaren (Dokumentationskommentare und mehrzeilige Kommentare werden nun auch erkannt). Meiner Meinung nach sieht jetzt der farblich gekennzeichnete Quellcode genauso aus, wie er es auch in der .Net Entwicklungsumgebung tut (von der Färbung von .Net Klassen einmal abgesehen).
Der Quellcode:

Donnerstag, 9. September 2010

String vs Stringbuilder

Zeichenketten werden in C# meistens mit dem Datentyp string dargestellt.
Wird ein String einmal initialisiert, ist er nicht mehr veränderbar. Operationen, die auf Strings ausgeführt werden (wie zum Beispiel Replace() oder Trim()), lassen das Original unverändert und ändern stattdessen eine Kopie, welche sie dann zurückgeben.
Um im .Net Framework zur Laufzeit änderbare Strings zu benutzen, ist die Klasse StringBuilder nötig.
Instanzen dieser werden wie Klassen über den new Operator angelegt und können dann dynamisch verändert werden.
Operationen werden nun direkt am Objekt durchgeführt:

StringBuilder DynamicString = new StringBuilder("Ersetze mich");
DynamicString.Replace("Ersetze mich", "Ersetzt.");
MessageBox.Show(DynamicString.ToString());

DynamicString enthält nach dem Ersetzen den Wert "Ersetzt", bei einem String wäre dies nicht der Fall.
Wie man an dem Code sehen kann, muss eine Zeichenkette vom Typ StringBuilder explizit in einen String konvertiert werden, wenn ein String verlangt wird.
Diese technischen Details der Implementierungen werden allerdings die wenigsten interessieren, die Klasse StringBuilder hat noch eine sehr viel bessere Eigenschaft, die sie sehr interessant macht: Die Geschwindigkeit bei der Verarbeitung.
Die Verarbeitung von Zeichenketten über den Typ String ist im Allgemeinen recht langsam.
Liest man beispielsweise eine lange Textdatei ein und schreibt den Inhalt in einen String, nimmt diese Aktion sehr viel Zeit in Anspruch.
Das folgende Codebeispiel verkettet 100000-mal das Wort "zeichenkette":

string OrdinaryString = "";
for (int i = 0; i < 100000; i++)
{
    OrdinaryString += "zeichenkette";
}

Das Programm benötigt zur Ausführung bei Verwendung des Typs String auf meinem Laptop mehr als 1 Minute.
Die gleiche Aufgabe schafft es bei Verwendung des Typs StringBuilder ohne merkliche Zeitverzögerung, das Ergebnis ist sofort da!

StringBuilder BetterString = new StringBuilder();
for (int i = 0; i < 100000; i++)
{
    BetterString.Append("zeichenkette");
}

Bei der Arbeit mit längeren Zeichenketten sollte man also auf jeden Fall die Klasse StringBuilder verwenden, denn diese bringt einen unglaublichen Zeitvorteil mit sich - allerdings muss auch gesagt werden, dass String bei ziemlich kurzen Zeichenketten effektiver ist.
Den gleichen "Trick" kann man auch anwenden, wenn man längere Texte in eine TextBox schreiben möchte. Die Eigenschaft Text des Steuerelements ist ebenfalls als String umgesetzt. Man sollte daher den längeren Text zuerst in einem StringBuilder zusammenbauen und dann diesen als Ganzes dem Textfeld zuweisen.

Dienstag, 7. September 2010

C# Kommentare

Die Programmiersprache C# unterstützt 3 Kommentartypen:
Einzeilige Kommentare, mehrzeilige Kommentare und Dokumentationskommentare.
Einzeilige Kommentare werden durch das Zeichen // eingeleitet und gehen bis zum Ende der aktuellen Zeile:
namespace ConsoleApplication1 // dies ist ein einzeiliger Kommentar

Mehrzeilige Kommentare erstrecken sich zwischen den Zeichen /* und */ und können, wie der Name schon sagt, über mehrere Zeilen gehen:

/* Dies ist ein Kommentar,
* der über mehrere Zeilen
* geht. */


Schließlich gibt es noch Dokumentationskommentare, welche durch das Zeichen /// eingeleitet werden.
Diese sind eigentlich ein Thema für sich und gehören nicht zu den eigentlichen Codekommentaren, denn sie haben eine XML - Struktur und dienen der automatischen Codekommentierung.
Dokumentationskommentare werden direkt vor das Objekt geschrieben, dass sie kommentieren sollen, die Entwicklungsumgebung fügt automatisch bestimmte Tags hinzu.
Das Thema soll hier nicht weiter ausgeführt werden, nur ein Beispiel wie die Kommentierung für die main - Methode aussehen könnte:

/// <summary>
/// Hauptmethode des Programms
/// </summary>
/// <param name="args">Befehlszeilenargumente, mit denen das Programm aufgerufen wurde</param>

Montag, 6. September 2010

Emails senden

Hinweis: Dieser Post erklärt die Grundlagen des Sendens von Emails. Zur Zeit des Posts war dies noch ohne SSL möglich, heutzutage ist dies jedoch meist Voraussetzung. Daher erkläre ich das Senden von Emails unter Benutzung einer SSL-Verbindung in diesem neuen Post.

Erstaunlicherweise können Emails über C# mit nur wenigen Anweisungen versandt werden.
Die Klasse System.Net.Mail stellt die hierfür nötigen Funktionen bereit und muss daher im Projekt mittels using eingebunden werden.
Eine neue Email kann dann als Instanz der Klasse MailMessage erstellt werden.
Die Absenderadresse wird über die Eigenschaft From eingestellt, welche ein Objekt vom Typ MailAddress aufnimmt. To, Body und Subject sind vom Typ String und bezeichnen die Empfängeradresse, den Nachrichtentext und den Betreff der Nachricht.
Zum Versenden der Email wird eine Instanz der Klasse SmtpClient benötigt.
Diese erwartet im Konstruktor die Adresse des zu nutzenden Postausgangsserver (muss vom Typ SMTP sein) sowie den zu nutzenden Port.
Manche Emailserver erwarten vor dem Senden von Emails eine Anmeldung am Server. Dazu muss dann eine Instanz der Klasse System.Net.NetworkCredential angelegt werden, im Konstruktor werden Benutzername und Passwort übergeben.
Die Instanz wird dann der Eigenschaft Credentials der MailMessage Klasse zugewiesen.
Folgendes Beispiel ist ein kleine Konsolenanwendung, die eine neue Email mit den anhand der Daten erstellt und diese sendet:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail; // hinzufügen

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            MailMessage Email = new MailMessage();

            Console.WriteLine("Absender:");
            MailAddress Sender = new MailAddress(Console.ReadLine());
            Email.From = Sender; // Absender einstellen

            Console.WriteLine("Empfänger:");
            Email.To.Add(Console.ReadLine()); // Empfänger hinzufügen

            Console.WriteLine("Betreff:");
            Email.Subject = Console.ReadLine(); // Betreff hinzufügen

            Console.WriteLine("Nachrichtentext:");
            Email.Body = Console.ReadLine(); // Nachrichtentext hinzufügen

            Console.WriteLine("Postausgangsserver:");
            string ServerName = Console.ReadLine();
            Console.WriteLine("Port:");
            string Port = Console.ReadLine();

            SmtpClient MailClient = new SmtpClient(ServerName, int.Parse(Port)); // Postausgangsserver definieren

            Console.WriteLine("Anmeldung erforderlich?"); // "Ja" oder "Nein" als Eingabe möglich

            bool LoginNecessary = (Console.ReadLine() == "Ja");
            if (LoginNecessary)
            {
                Console.WriteLine("Benutzername:");
                string UserName = Console.ReadLine();
                Console.WriteLine("Passwort:");
                string Password = Console.ReadLine();
                System.Net.NetworkCredential Credentials = new System.Net.NetworkCredential(UserName, Password);

                MailClient.Credentials = Credentials; // Anmeldeinformationen setzen*/
            }

            MailClient.Send(Email); // Email senden

        }
    }
}

Diese Methode zum Versenden von Emails funktioniert mit allen Emailprovidern, die als Postausgangsserver einen SMTP Server haben.
Wichtig ist, dass als Absender die tatsächliche Emailadresse eingegeben wird und die Serverinformationen stimmen (diese sind die gleichen wie im Emailprogram, z.B. Outlook, unter Kontenoptionen eingestellt).
Für den kostenlosen Emailanbieter WEB ist die Adresse des Postausgangsserver beispielsweise "smtp.web.de" und der richtige Port 25.
Beim ebenfalls kostenlosen Anbieter GMX muss der Server auf "mail.gmx.net" festgelegt werden und der Port wiederrum auf 25.
Die meisten Anbieter benötigen zum Versenden von Emails Anmeldeinformationen, WEB und GMX beispielsweise gehören auch dazu, hier muss also die Eigenschaft Credentials definiert werden.

Freitag, 3. September 2010

Unterschied zwischen Wert- und Verweistypen

In der Programmiersprache C# gibt es, wie bei vielen Programmiersprachen, grundsätzlich 2 Datentypvarianten: Es gibt Werttypen und Verweistypen (oder Referenztypen).
Variablen, die auf Werttypen basieren, speichern den tatsächlichen Wert dieser Variablen. Im Gegensatz dazu speichern Variablen, die auf Verweistypen basieren, nur einen Verweis auf den Speicherplatz des Wertes der Variablen.
Weiterhin werden diese beiden Typvarianten auf unterschiedliche Art gespeichert: Werttypen werden im Stapel gespeichert, Verweistypen in einem eigenen Speicherbereich, dem Heap.
Kopiert man den Inhalt eines Werttyps, wird der Wert kopiert, danach existieren 2 Variablen mit dem gleichen Wert. Kopiert man den Inhalt eines Verweistyps, wird lediglich der Verweis kopiert, es existieren dann 2 Verweise, die auf den gleichen Wert im Heap verweisen. Ändert man also den Inhalt der ursprünglichen Verweisvariablen, ändert sich auch der Inhalt der kopierten Verweisvariablen, da sie auf den gleichen Speicherplatz zeigt.
Die meisten Typen in C# sind Werttypen, wie zum Beispiel byte, int und char. Verweistypen sind generell nur Klassen und Arrays. Wofür braucht man nun diese Unterscheidung beim Programmieren?
Unvermeidlich wird ein Wissen über Datentypvarianten, wenn man Methoden mit Parametern benutzt. Folgendes einfaches Beispiel sollte dies verdeutlichen:

        private void Form1_Load(object sender, EventArgs e)
        {
            // Werttypen
            int NumberA = 8;
            int NumberB = 3;

            // Verweistyp
            int[] Numbers = { 8, 3 };

            int NumberC = ResultValue(NumberA, NumberB);
            int NumberD = ResultReference(Numbers);
        }

        private int ResultValue(int numberA, int numberB)
        {
            numberA /= 2; // numberA halbieren
            return numberA * numberB;
        }

        private int ResultReference(int[] numbers)
        {
            numbers[0] /= 2; // 1. Zahl im Array halbieren
            return numbers[0] * numbers[1];
        }

Es gibt 2 Methoden, ResultValue() und ResultReference(), welche aus Form_Load() aufgerufen werden. Erstere erhält 2 Variablen vom Typ Integer als Parameter, die Zahlen 8 und 3. In der Methode wird die 1. Zahl (8) halbiert, und das Produkt beider Zahlen (4 * 3 = 12) zurückgegeben.
In der 2. Methode ResultReference() wird ein Array vom Typ Integer als Parameter übergeben, in welchem auch 2 Zahlen (8 und 3) gespeichert sind.
Es wird ebenfalls die erste Zahl halbiert und das Produkt zurückgegeben (4 * 3 = 12). Allerdings sind die Integer - Parameter der ersten Methode Werttypen, bei der Übergabe an ResultValue() wird also von ihnen eine Kopie im Speicher erzeugt, die Halbierung der ersten Zahl wird also nur bei der Kopie vorgenommen, die Originalzahl, NumberA, ist nach Rücksprung aus der Methode immer noch 8.
Das an ResultReference() übergebene Array ist allerdings ein Verweistyp, bei der Übergabe des Parameters an die Methode wird lediglich der Verweis kopiert, er zeigt aber auf die gleiche Speicherposition im Heap. Wird dann in der Methode die erste Zahl im Array halbiert, ist das eine Änderung am Original, nach Rücksprung der Methode ist der Wert der ersten Zahl in Numbers gleich 4.

Um dieses Verhalten zu ändern, gibt es das Schlüsselwort ref. Wird dieses vor einen Werttyp - Parameter gestellt, wird dieser als Verweistyp behandelt und bei der Übergabe keine Wertkopie erstellt, sondern der Verweis auf das Original übergeben:

            // Werttypen
            int NumberA = 8;
            int NumberB = 3;

            int NumberC = ResultValue(ref NumberA, ref NumberB);

Im obigen Beispiel wird dann in der Methode das Original, NumberA, halbiert.
Um Verweistypen in Werttypen umzuwandeln gibt es kein entsprechendes Schlüsselwort, bei der Parameterübergabe muss manuell vom zu übergebenden Objekt eine echte Kopie, eine deep copy, erstellt werden.

Donnerstag, 2. September 2010

Listen sortieren

Listen werden im .Net Framework durch die Klasse List<T> repräsentiert, wobei T einen bestimmten Datentyp angibt, die Listen sind also typisiert, heißt sie nehmen zwecks Datenkonsistenz nur Objekte eines Typs auf.
In diesem Post geht es um die Sortierung von Listen, da im vorigen Post aber bereits auführlich die Sortierung von Arrays erklärt wurde, fällt dieser etwas kürzer aus. Bei Arrays wurde die statische Funktion Array.Sort() benutzt, bei Listen muss die Instanzfunktion benutzt werden. Das bedeutet, dass bei Arrays die Funktion von der nicht instanzierten Klasse Array aufgerufen werden konnte, bei Listen muss die Funktion von einer Instanz der Klasse List aufgerufen werden, also zum Beispiel MeineAngelegtListe.Sort().
Folgender Beispielcode sortiert die Liste TestList absteigend:

List<int> TestList = new List<int>(){5, 1, 2, 4, 3}; // Kurzschreibweise zur Erzeugung von gefüllten Listen
TestList.Sort(); // sortiert die Liste aufsteigend
TestList.Reverse(); // kehrt die Reihenfolge der Objekte in der Liste um, die Elemente sind so absteigend geordnet

Mittwoch, 1. September 2010

Arrays sortieren

Eine sehr wichtige Funktion im Umgang mit Daten ist das Sortieren dieser.
Das .Net Framework stellt eine Menge Methoden dafür bereit, Arrays zum Beispiel lassen sich sehr leicht über die Methode Array.Sort() sortieren.
Diese sortiert das übergebene Array aufsteigend mit Hilfe des Quicksort - Algorithmus, welcher einer der besten Sortieralgorithmen ist.
Folgendes Beispiel sortiert ein integer - Array aufsteigend nach ihrer Größe (bei Buchstaben und Wörtern werden diese alphabetisch geordnet):

int[] TestArray = new int[] { 5, 3, 4, 1, 2 }; // Kurzschreibweise zur Erstellung von Arrays
Array.Sort(TestArray);

Das Ergebnis ist anschließend direkt in TestArray gespeichert, d.h. die Manipulation der Daten wurde direkt am Array vorgenommen, da in .Net Array - Typen Verweis - Typen sind.
Um das Array absteigend zu sortieren, kann nach der Sortierung einfach die Methode Array.Reverse() aufgerufen werden, welche das Array umkehrt:
Array.Reverse(TestArray);
Für an der Theorie Interessierte und aus Werbung an der eigenen Sache, hier findet ihr eine Android App von mir, die verschiedene Sortieralgorithmen (u. a. Quicksort) visualisiert.