-
ACHTUNG - NEUES BLOG
Ab sofort steht unter http://devtyr.norberteder.com mein neues Blog zur Verfügung. Dieses Blog wird nicht weiter betreut, bleibt aber erhalten. Neue Eintr%auml;ge erfolgen nur mehr im neuen Blog. Kommentare werden ebenfalls nicht mehr behandelt. Wer weiterhin meinen Einträgen und Aktivitäten folgen möchte, möge bitte RSS-Feeds, Verlinkungen etc. an die neue Location anpassen.
|
Extern aliases: Gleichen Namespace aus unterschiedlichen Assemblies nutzen
16.01.07 - .NET, Grundlagen, Base Framework Beitrag von Norbert Eder| | Das .NET Framework < 2.0 unterstützte lediglich eine einzelne Namespace-Hierarchie. In diese wurden die Typen der referenzierten Assemblies geladen und konnten anschließend verwendet werden. Dies ist allerdings eher unschön, wenn beispielsweise die gleiche Assembliy, allerdings in unterschiedlichen Versionen, verwendet werden muss oder eine benötigte Assembly zufällig denselben Namespace benutzt wie eine ganz andere. Mit extern aliases ist dieses Problem zu lösen.
Gegeben sind zwei Assemblies.
Assembly a1.dll
namespace N
{
public class A {}
public class B {}
}
Assembly a2.dll
namespace N
{
public class B {}
public class C {}
}
Bei nachfolgendem Programm würde es nun zu einem entsprechenden Fehler gelangen:
class Test
{
N.A a; // Ok
N.B b; // Fehler
N.C c; // Ok
}
Kompilieren wir nun den Code mit folgender Anweisung:
csc /r:a1.dll /r:a2.dll test.cs
Die Typen aus den Assemblies a1.dll und a2.dll werden in der Global Namespace Hierarchy abgelegt, wodurch ein Fehler entsteht: Der Typ N.B existiert in beiden Assemblies. An dieser Stelle kommen die extern aliases zum Einsatz:
extern alias X;
extern alias Y;
class Test
{
X::N.A a;
X::N.B b1;
Y::N.B b2;
Y::N.C c;
}
Es werden die beiden Aliase X und Y deklariert, aber die Defintionen der Aliase sind extern abgelegt. Der Kompilierungsaufruf muss entsprechend abgeändert werden und sieht so aus:
csc /r:X=a1.dll /r:Y=a2.dll test.cs
Unter Verwendung von Visual Studio können die Aliase in der Eigenschaft Aliases der jeweiligen Referenz angegeben werden.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Mit IComparable nach mehreren Eigenschaften sortieren
16.01.07 - .NET, Grundlagen, Base Framework Beitrag von Norbert Eder| | Nehmen wir als Beispiel eine Highscore-Liste. Hierfür müssen zwei Werte sortiert werden:
- der erreichte Score (absteigend)
- der Name des Spielers (aufsteigend)
Mit Hilfe der Schnittstelle IComparable kann dies einfach erledigt werden. Hierfür benötigen wir die Datenklasse Highscore, welche besagtes Interface implementiert:
using System;
using System.Collections.Generic;
using System.Text;
namespace HighscoreTest
{
public class Highscore : IComparable
{
private string _name = String.Empty;
private int _score = 0;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
public int Score
{
get { return this._score; }
set { this._score = value; }
}
public Highscore(string name, int score)
{
this._name = name;
this._score = score;
}
public override string ToString()
{
return this._name.PadRight(20, ' ') + this._score;
}
#region IComparable Members
public int CompareTo(Highscore other)
{
if (this._score.CompareTo(other._score) == 0)
return this._name.CompareTo(other._name);
else
return this._score.CompareTo(other._score) * (-1);
}
#endregion
}
}
Wie in der Methode CompareTo zu sehen ist, ist eine signifikante Eigenschaft auszuwählen. Diese ist die Eigenschaft, die vorrangig sortiert werden soll. In unserem Fall der Score. Sind die zu vergleichenden Werte identisch, wird der Name sortiert.
Getestet werden kann dies mit Hilfe der folgenden Zeilen:
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Diagnostics;
namespace HighscoreTest
{
class Program
{
static void Main(string[] args)
{
List highscoreList = new List();
highscoreList.Add(new Highscore("Norbert2", 17));
highscoreList.Add(new Highscore("Norbert1", 17));
highscoreList.Add(new Highscore("Norbert3", 3));
highscoreList.Add(new Highscore("Karl", 3));
highscoreList.Sort();
Debug.WriteLine("Highscore");
Debug.WriteLine("--------------------");
foreach(Highscore hscore in highscoreList)
Debug.WriteLine(hscore);
}
}
}
Wie zu sehen ist, gar nicht so schwierig und keinesfalls aufwändig.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Es muss nicht immer AJAX sein ...
14.01.07 - Entwicklung, Diskussionen, .NET, Grundlagen, ASP.NET Beitrag von Norbert Eder| | Wer AJAX nicht einsetzt ist doof. Hört man zumindest Vögel zwitschern. Aber es gibt auch andere Möglichkeiten.
Für viele Dinge ist es zudem auch gar nicht nötig, AJAX einzusetzen, da simple JavaScripts durchaus ausreichen. So ist vor dem Einsatz von AJAX darüber nachzudenken, welcher Zweck erfüllt werden soll und ob es nicht andere - einfachere - Lösungen gibt.
Wer zudem fit in C++ ist, hat die Möglichkeit auf binary HTML Components [1] zu setzen. Zugegeben, schon recht alt, aber funktioniert sehr flott - und ein riesiges Framework ist auch nicht notwendig.
Implementing Binary DHTML Behaviours
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Eigenschaften und Zugriffsmodifizierer
12.01.07 - .NET, Grundlagen, Base Framework Beitrag von Norbert Eder| | Man nehme folgendes Interface:
Interface
public interface IPerson
{
string Firstname { get; set; }
string Lastname { get; set; }
DateTime Birthday { get; }
}
Dieses Interface beschreibt, dass die Eigenschaft Birthday nur gelesen werden darf, ein Setzen ist nicht möglich. Um dies aber in der Assembly zu erlauben, in der sichi auch das Interface befindet kann folgendes definiert werden:
public class Person : IPerson
{
private string _firstname = null;
private string _lastname = null;
private DateTime _birthday;
public string Firstname
{
get { return this._firstname; }
set { this._firstname = value; }
}
public string Lastname
{
get { return this._lastname; }
set { this._lastname = value; }
}
public DateTime Birthday
{
get { return this._birthday; }
internal set { this._birthday = value; }
}
}
Der internal Zugriffsmodifizierer sorgt dafür, dass der Setter in derselben Assembly aufgerufen werden kann. Dies ist in vielen Fällen sehr hilfreich.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Generische Methoden und deren Aufruf
12.01.07 - .NET, Grundlagen Beitrag von Norbert Eder| | Einfach auf der Zunge zergehen lassen oder in eine Consolen-Anwendung kopieren und austesten.
class Program
{
static void Function<T>(int x, T y)
{
Console.WriteLine("Function 1");
}
static void Function<T>(T x, long y)
{
Console.WriteLine("Function 2");
}
static void Main()
{
Function<int>(5, 324);
Function<byte>(5, 324);
Function(5, 324);
Console.WriteLine();
}
}
| | | 3 Kommentare
- 961 mal angesehen
| 0 Trackbacks
| Permalink | Trackback-URL |
Variable Anzahl an Methoden-Parametern
08.01.07 - .NET, Grundlagen Beitrag von Norbert Eder| | Wer eine variable Anzahl an Parametern in einer Methode benötigt, der hat vermutlich bereits das Schlüsselwort params entdeckt. Wer nicht, dem sei es hiermit erklärt:
Das Schlüsselwort params ermöglicht es, einer Methode eine beliebige Anzahl an Parametern zu übergeben. Im Gegensatz zu einem Array können die einzelnen Werte mit Hilfe eines Komas getrennt werden, so wie es beispielsweise auch bei einem String.Format funktioniert.
Im folgenden Beispiel wird eine generische Liste durch eine Methode AddMultipleStringsToList erweitert, welche diese Funktionalität bietet:
public class MultipleStringList : List<string>
{
public void AddMultipleStringsToList(params string[] values)
{
foreach (string s in values)
this.Add(s);
}
}
Zusätzlich zu den Methoden Add und AddRange ist nun die neue Methode AddMultipleStringsToList verfügbar, die folgendermaßen verwendet werden kann:
MultipleStringList mStringList = new MultipleStringList();
mStringList.AddMultipleStringsToList("test1", "test2", "test3", "test4");
foreach (string s in mStringList)
Console.WriteLine(s);
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Schlüsselwort sealed
06.01.07 - .NET, Grundlagen Beitrag von Norbert Eder| | Von einer Klasse die mit dem sealed-Schlüsselwort gekennzeichnet ist, kann nicht vererbt werden (sealed = versiegelt). Dies bedeutet, dass Erweiterungen nicht gewünscht sind bzw. eine weiterer Abstraktion ohnehin sinnlos wäre. Aufrufe an versiegelte Klassenmember können durch Laufzeitoptimierungen beschleunigt werden.
Beispiel
public sealed class TestClass
{
private int _a = 0;
private int _b = 0;
public int A
{
get { return this._a; }
set { this._a = value; }
}
public int B
{
get { return this._b; }
set { this._b = value; }
}
}
Ergänzungen
Strukturen (structs) sind per Definiton sealed und können daher nicht vererbt werden.
Eine Verwendung von sealed gemeinsam mit abstract ist nicht erlaubt, da man bei einer abstrakten Klasse davon ausgehen kann, dass die konkrete Implementierung nicht existiert.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL |
Paper zur Common Language Infrastructure (CLI)
01.01.07 - .NET, Grundlagen Beitrag von Norbert Eder
Design und Implementierung der .NET Generics
22.12.06 - .NET, Grundlagen Beitrag von Norbert Eder
Einführung Garbage Collector
11.01.06 - .NET, Grundlagen Beitrag von Norbert Eder| | Garbage Collection unter C# sieht im Prinzip folgendermaßen aus:
Der GC wird meist dann angetriggert, wenn der Heap-Speicher aufgebraucht sprich voll ist, manuell gestartet wird, oder wenn ein anderes Programm mehr Speicher benötigt, als aktuell noch frei ist.
Der GC iteriert durch den Heap und markiert zuerst jedes Objekt als Garbage, also setzt es auf "zu verwerfen". Danach wird nochmals jedes Objekt rekursiv überprüft, ob Referenzen darauf zeigen - es also noch benutzt wird. Jedes Mal, wenn ein Objekt vom Garbage Collector besucht wird, wird es als erreichbar markiert. Nach diesem Durchlauf steht nun fest, welche Objekte erreichbar sind und welche nicht. Zyklische Referenzen (also Objekt A referenziert Objekt B, welches Objekt C referenziert, welches wiederum Objekt A referenziert) werden ebenfalls entsprechend behandelt.
Im nächsten Schritt wird der Managed Heap durchlaufen und dieser kompaktiert. Das bedeutet, dass Objekte, die verworfen werden können durch Objekte, die im Heap weiter oben gelagert sind überschrieben werden. Dadurch verkleinert sich der Heap und benötigte Objekte wandern weiter nach unten. Es entstehen also keine "Löcher" Heap (Fragmentierung). Dadurch müssen natürlich auch alle Referenzen vom GC geändert werden. Dies ist natürlich ein aufwändiges Unterfangen und aus diesem Grund sollte der GC manuell nur aufgerufen werden, wenn dies unbedingt notwendig ist.
Wann werden Objekte nicht mehr benötigt? Beispielsweise werden in einer Methode unterschiedliche Objekte instanziert. Wurde diese Methode durchlaufen, werden diese Objekte natürlich nicht mehr benötigt und werden beim nächsten Durchlauf des GC entsprechend behandelt. Sie müssen also nicht explizit auf null gestellt werden. Anders verhält es sich bei Objekten, die "expensive resources" (Dateien, Socket-Verbindungen, Ports, Daten Strukturen etc.) enthalten. Hier bietet .NET die object finalization an. Werden also Verbindungen etc. benutzt sollte eine Methode Finalize() vorhanden sein. Diese wird bei der Freigabe des Objektes aufgerufen und somit können verwendete Resourcen auch entsprechend behandelt bzw. tatsächlich freigegeben werden. Hier ist zu beachten, dass die Finalize()-Methode der Basisklasse auch aufgerufen wird. Weiters immer einen try-catch-Block darum ziehen.
Eine weitere Möglichkeit besteht durch das Dispose()-Pattern. Hier ist eine Methode Dispose() zu implementieren. Durch den Aufruf von Dispose werden alle teuren Resourcen entsprechend freigegeben - wie auch in der Finalize()-Methode muss hier der Code für die Freigabe der Ressourcen manuell eingetragen werden. Die Ressourcen werden durch diesen Aufruf sofort freigegeben - ausser man wartet auf den Garbage Collector.
Die schönere Variante besteht darin, das IDisposable()-Interface zu implementieren. Dadurch wird die Methode Dispose() vorgeschrieben und muss entsprechend implementiert werden.
Natürlich gäbe es an dieser Stelle noch mehr zu sagen, aber das sollte als kurzer Überblick durchaus reichen.
| | | Kommentar hinzufügen
| 0 Trackbacks
| Permalink | Trackback-URL | Zurück Weiter
|
|
|
|
|
|
|