Original von Fabian
Du kannst nur das CurrentDirectory umstellen und die Dateien dann mit DllImport einbinden. Eine andere Möglichkeit, außer CodeDom, fällt mir auch nicht ein.
Benutzt du nicht eine Bibliothek, die ich dir gebastelt habe mit der man dynamisch DLLs laden und entladen kann?
Ganz zu schweigen davon, dass CodeDOM dafür da ist um Source code zu erzeugen oder Source code zu kompilieren. Und zwar im Sinne von einer IDE, oder Scripting durch den User.
CodeDOM zu missbrauchen um dynamisch IL zu erzeugen ist doch total krank, dafür gibt es Reflection.Emit.
Für's einfach Laden geht auch das hier
Original von onlinegurke
@HansDampf:
...mit denen aber schwer umzugehen ist, da ist CodeDOM noch einfacher zu verstehen...
Dynamische IL ist ja auch nichts, was ein Application Dev mal einfach so machen sollte.
CodeDOM ist dafür da Source Code zu erzeugen, siehe wsdl.exe oder xsd.exe.
Das ist abartig langsam wenn man es dazu missbraucht wiederholt on-the-fly IL zu erzeugen und benötigt temporäre Dateien.
In diesem Fall ist beides die sprichwörtliche Kanone für die Spatzenjagd. Ein generischer Container wie DataTable würde es genauso tun.
Original von BerndFfm
Hallo Cryo,
für so eine einfache SQL-Abfrage nimmt man eigentlich einen DataReader.
Das Ergebnis ist dann in dr[0] (wenn dr der DataReader ist).
Wenn schon einen DataReader hernehmen, dann gleich richtig und das Ergebnis mit reader.GetInt32(0) holen. ;-)
Wenn du den Indexer des Readers nutzt, könntest du ja gleich ExecuteScalar vom Command benutzen.
Hätte beides den gleichen Overhead...
Original von svenson
Ach, dass auch die Klasse statisch sein muss, war mir entgangen. Das entkräftet zumindest die meisten der Kritikpunkte. Die unsichtbaren Kopplungen bleiben allerdings. Aber da Extensions ja im IL-Code ausgezeichnet werden, kann ein Visualisierungstool diese Beziehungen ja wenigstens sichtbar machen.
Ex-Methods sind nix weiter als statische Methoden, die mit dem ExtensionAttribute markiert werden, die Klasse selbst muss ebenfalls statisch sein und auch mit dem gleichen Attribut markiert sein.
Das ganze existiert auch nur in deinem Source, nicht im IL code.
Dem Compiler wird durch die Attribute nur gezeigt, dass er diese komische Methode, die er gar nicht in der Klasse finden kann, in einer andere Klasse suchen könnte.
Der Namespace der Extension class muss übrigens ebenfalls als using-clause benutzt werden.
Zitat
Ist in Extension Methods eigentlich der Zugriff auf private Member der zu erweiternden Klasse erlaubt? Dürfte ja eigentlich nicht der Fall sein.
Wie gesagt: keine Zauberei, nur statische Methoden.
Und wirklich Sinn macht das eigentlich nur bei generischen Methoden.
Nehmen wir mal einen abtrakten Bleistift:
[Extension]
public static class Miep
{
[Extension]
public static IEnumerable<T> GetItemsGreaterThan<T>(IEnumerable<T> items, IComparable<T> minValue)
{
foreach(T item in items)
if(minValue.CompareTo(item) < 0)
yield return item;
}
}
Das ganze ließe sich jetzt so aufrufen:
int[] someInts = {1, 2, 3, 4, 5, 6};
foreach(int found in Miep.GetItemsGreaterThan<int>(someInts , 3))
Console.WriteLine(found);
IMHO hübscher wäre es so:
int[] someInts = {1, 2, 3, 4, 5, 6};
foreach(int found in someInts.GetItemsGreaterThan(3))
Console.WriteLine(found);
Wenn man es sinnvoll verwendet, lassen sich auf die Art etwas zu wortreiche Zeilen schön vereinfachen. (Für den Leser)
LINQ selbst benutzt Ex-Methods nur indirekt, da wir es dort mit syntaktischen Tricks zu tun haben, die wieder über syntaktische Tricks gestülpt werden.
Wenn deine Klasse/Interface zum Beispiel kein OrderBy enthält, aber irgendeine Extension class eine passende Methode zur Verfügung stellt, dann wird dieses OrderBy benutzt.
Praktisch eine Art Duck-typing für statische Methoden.
btw: Was wirklich interessant an Ex-Methods ist, ist die Frage ob MS sie weit genug abgespeckt hat, um die Patente von CodeGEAR/Borland zu Class helpers nicht zu verletzen.
Stell' dir Boxing einfach so vor, dass eine Instanz einer Klasse erzeugt wird, die deinen ValueType als Feld besitzt. Unboxing kannst du dir vorstellen, als wenn der Wert dieses Feldes wieder zurückgegeben wird.
Das ist nicht 100% exakt, aber genau genug um es sich besser vorstellen zu können.
Ein boxed ValueType verhält sich in vielerlei Hinsicht wie ein Referenztyp.
Bleistift:
struct Sample
{
public int Field;
public override ToString()
{
return Field.ToString();
}
}
static void Miep(object instance, object value)
{
FieldInfo fi = instance.GetType().GetField("Field");
fi.SetValue(instance, value);
}
static void Main()
{
Sample s = new Sample();
s.Field = 1;
object o = s;
Miep(o, 2);
Console.WriteLine(o); // ergibt 2!
}
Original von der-basti
Ich bins nochmal.
Und zwar habe ich ein Problem mit dem "SortedSet".
Wie wende ich es auf eine IList an? Wenns geht mit CodeSnippes.
Vielleicht verwenden wir beide einfach nur unterschiedliche Begriffe für die Benennung "Set", aber wie um alles in der Welt sollte ein Index bei einem Set auch nur ansatzweise sinnvoll sein?
ICollection<T> könnte ich voll und ganz nachvollziehen, aber IList<T>?
Original von Borg
Ist in meinen Augen aber kein Bug, sondern falsch programmiert, da sich alle Threads eine (relativ) globale Variable line teilen. Dies kann natürlich nicht gut gehen.
Im anderen Beispiel hat ja jeder Thread eine lokale Variable (entspricht also dem o.g. ParametrizedThreadStart) und alles ist schick.
Ooops, wollte Bug in Anführungszeichen setzen.
Der Compiler kann ja schlecht wissen, dass es hier asynchrone Calls sind und er wird unwissend drauflosoptimieren.
Original von Borg
Klassische Race-Condition.
Wahrscheinlich hast du eine Variable, die dem Thread angibt, welche Zeile er sich nehmen soll.
IMHO der kassische C# Bug, der lokale, threaded, anonyme Methoden innerhalb einer Schleife betrifft.
Kann man sehr einfach reproduzieren:
"Funktioniert" gibt a, b und c in irgendeiner Reihenfolge. "FunktioniertNicht" gibt meistens c, c und c, da das Feld der compiler generierten Klasse für die anonyme Methode immer wieder überschrieben wird.
static Random r = new Random();
static void Main(string[] args)
{
string[] lines = { "a", "b", "c" };
Funktioniert(lines);
FunktioniertNicht(lines);
}
private static void WaitForAll(IEnumerable<Thread> threads)
{
foreach(Thread thread in threads)
{
if ((thread.ThreadState & ThreadState.Running) == ThreadState.Running)
thread.Join();
};
}
private static void FunktioniertNicht(string[] lines)
{
List<Thread> threads = new List<Thread>(lines.Length);
foreach (string line in lines)
{
ThreadStart ts = delegate()
{
Thread.Sleep(r.Next(200));// zufällige dummy-latenz
Console.WriteLine(line);
};
Thread thread = new Thread(ts);
thread.Start();
threads.Add(thread);
}
// warte bis alle färtsch sind
WaitForAll(threads);
}
private static void Funktioniert(string[] lines)
{
List<Thread> threads = new List<Thread>(lines.Length);
foreach (string line in lines)
{
threads.Add(RunThreaded(line));
}
// warte bis alle färtsch sind
WaitForAll(threads);
}
private static Thread RunThreaded(string line)
{
ThreadStart ts = delegate()
{
Thread.Sleep(r.Next(200));// zufällige dummy-latenz
Console.WriteLine(line);
};
Thread result = new Thread(ts);
result.Start();
return result;
}
@svenson
Ich denke spätestens wenn er mit der erzeugten Instanz arbeiten will, wäre die Frage gekommen. *g*
Mir ging's nur darum eine Lösung zu zeigen, wie man auch ohne dynamischen Code (also auch ohne spezielle Berechtigungen) eine generische Methode so verpacken kann, dass man sie ohne Typenparameter wiederholt aufrufen kann.
Generics sind eine Compilezeit-Angelegenheit. Den Typ kann man nicht zur Laufzeit übergeben. No chance!
Es gibt immer noch Reflection.
Einmal in ein nicht generisches Delegate verpackt, kann man auch generische Methoden problemlos aufrufen.
// wie auch immer huskys Create-Methode aussieht
public static T Create<T>()
where T : new()
{
Console.WriteLine("Creating instance of type {0}...", typeof(T));
return new T();
}
public delegate object CreateMethod();
static CreateMethod WrapCreate<T>()
where T : new()
{
return delegate
{
return Create<T>();
};
}
public static CreateMethod Wrap(Type type)
{
MethodInfo m = typeof(Program).GetMethod("WrapCreate",
BindingFlags.Static | BindingFlags.NonPublic);
m = m.MakeGenericMethod(type);
return m.Invoke(null, null) as CreateMethod;
}
static void Main(string[] args)
{
Type optionalType = Type.GetType("Namespace.MyClass, MyDLL");
CreateMethod create = Wrap(optionalType);
for (int i = 0; i < 10; i++)
{
object instance = create();
}
}
Zitat
Du könntest höchstens zu Laufzeit Code erzeugen und diesen dann mit Microsoft.CSharp.CSharpCodeProvider oder System.CodeDom.Compiler.ICodeCompiler zur Laufzeit übersetzen.
Aua! Wenn man dynamisch IL code geniert, dann sollte man IL Code generieren. Einen CodeDom zur Laufzeit zu benutzen nur um etwas ausführen zu können ist absolut übertrieben und ineffizient.
DynamicMethod oder AppDomain.DefineDynamicAssembly kann man benutzen, je nachdem ob man nur eine Methode oder ganze Typen generieren will.
Zitat
Wenn es dir nur um die Erzeugung von Objekten des Typs T geht, dann benutze Activator.CreateInstance.
Würde ich hier auch vorschlagen, außer man will die Factory öfter aufrufen. (Activator ist verflucht langsam)
Genau dafür nehme ich es auch. Vllt. führt C# ja auch irgendwann Type aliases ein so wie sie in Pascal funktionieren. Wäre ja nicht das erste was sie aus Pascal/Delphi übernommen hätten.
Original von FZelle
Den grössten Nachteil von VB.NET sehe ich allerdings darin, das viel mehr
nicht Programmierer es benutzen, und die Tipps und Tricks deshalb
meisst Hundsmiserable sind.
Auch ist es leider immernoch so, das 80% aller VB.NET Entwickler eher friemeln
als strukturierte Herangehensweisen ( Pattern und CO ) zu lernen.
Klingt für mich wie eine Beschreibung des klassischen VB, sollte dem OP also nicht sehr schwer fallen. *g*
Zitat
Aber ich gebe Rainbird recht, in den Händen eines echten Entwicklers, sind beide
Sprachen gleich gut.
Und dann entwickelt VB.NET auch seinen Charme, wenn man dann mit
COM/ActiveX arbeitet.
Das gilt aber nur für widerliche IDispatch-basierte "Wär' mal gerne was Brauchbares geworden"-Libs.
Dynamic Invokes sind in .Net so abartig langsam, das sie IMHO ein no-go darstellen. Wenn ein compiler so krank ist und einfach so, ohne einen speziellen Switch zu aktivieren, dyn. Invokes generiert grenzt das an vorsätzliche CPU-Verschwendung. Und die wird ja bekannterweise mit 5 Jahren Brainfuck-programmieren bestraft. *g*
Original von John444
ich sollte also nur globale typen verwenden wenn ich sie auch wirklich häufiger brauche
sonst halt fall 2... richtig.
Ich finde es einfach übersichtlicher wenn zu komplexe typen nicht inline definiert sind.
Außerdem kann man die generierten Klassen aus inline-Typen eigentlich nur als Appetitzügler benutzen, oder als Brechmittel.
Das halte ich jetzt mal für ein Gerücht, zumal dass das Abbruchkriterium nicht immer ein Integer Wert sein muss.
In der Theorie kann der Compiler statische Teile der Abbruchbedingung so extrahieren, dass sie nur einmalig evaluiert werden müssen.
Also praktisch so wie ein Pascal-for funktioniert.
Zitat
Ein wirklicher Geschwindigkeitsvorteil bringt foreach im Gegensatz zu for, da hier die Elemente durchgegangen werden, ohne dass sich diese vom Wert verändern dürfen (kann also intern durch Pointerarithmetik abgehandelt werden).
Theoretisch ja, praktisch wird hier ein externer Iterator benutzt und diese Abstraktion kostet fast immer mehr.
Lässt sich aber auch in ein for quetschen :
for (IEnumerator<Miep> miepEum = list.GetEnumerator(); miepEum.MoveNext();)
{
if (miepEnum.Current == blabla)
DoSomething(miepEnum);
}
Zitat
@Robert G:
LOL es gibt schon unheimlich unheimliche Konstrukte ;-)
C-ish for-Schleifen sind allgemein dafür bekannt für unchristliche Dinge misbraucht zu werden.
Prost:
Ich hatte dich schon verstanden.
Du verfällst gerade dem gleichen Irrglauben, dem wir wohl alle irgendwann mal verfallen sind.
IIndividual und TestIndividual sind nunmal zwei verschiedene Typen.
Wenn du eine ICollection<TestIndividual> hast, bringt diese zum Bleistift eine Methode Add(TestIndividual item) mit, aber nicht Add(IIndividual item).
Zitat
und ich dachte genau das ist durch das ableiten von List<TestIndividual> geschehn (denn TestIndividual realisiert IIndividual). meine IDE sagt mir nun aber ich müsste die Schnittstellenmember extra noch mit Typ IIndividual implementieren. ich verstehe nicht wieso das noch nötig ist.
Sicher, der Compiler könnte rekursiv die gesamte Hierarchie runterrennen und für jedes implementierte Interface und jeden Vorfahren das generische Interface implementieren.
Aber das würde abartig viel niemals verwendeten Code generieren und vor allem will man das auch gar nicht.
Du hast dieses Interface ja nicht ohne jeden Grund geschaffen, deshalb die Frage: Warum muss die Liste beides als Elementtypen haben? Würde das Interface nicht reichen?
Und wenn es nicht reicht warum nicht?
Bzw muss sie jetzt auch noch unbedingt ICollection<1> deines Interfaces implementieren?
Wenn es für die letzten beiden Fragen tatsächlich gute Gründe gibt, kannst du immer noch selbst ICollection<IDings> explizit implementieren.
Ich denke aber, dass du dir wesentlich weniger Fesseln anlegst, wenn du nicht gegen eine fixe Klasse und somit nicht gegen einen fixen Vererbungszwang programmierst.
List<TestIndividual> implementiert ICollection<TestIndividual>, aber es implementiert nicht ICollection<IIndividual>.
Stelle dir mal vor was passieren würde, wenn der CSC rekursiv sämtliche Vorgänger und deren Interfaces implizit mit implementieren würde. 8o
Da hättest du sicherlich sehr schnell Assemblies die sehr groß sein würden.
Du musst hier alles von ICollection<IIndividual> explizit implementieren, was nicht bereits durch List<TestIndividual> gegeben ist. (Count, etc)
Aber vllt überlegst du dir, ob das wirklich das ist was du willst...
Warum muss sie überhaupt von der Klasse sein? Warum ist die Liste nicht gleich von dem Interface?
Original von Traumzauberbaum
Das solltest du aber nur bei sealed Klassen machen. Sonst setzt du implizit Anforderungen an die abgeleiteten Klassen, die man nicht sofort sieht.
Naja, es spricht eigentlich fast nix dagegen Kassen zu versiegeln, wenn eine Ableitung keinen wirklichen Nutzen bringt.
Und ja, du hast Recht. Das abweichen von den MS-Normen bzw. den geläufigen Normen (müssen ja nicht ewig die von MS bleiben ) sollte sich einen Hinweis in den Docs verdienen...
Original von talla
@ Robert G
Schau dir mal Herbivores Link an. So empfiehlt es auch Microsoft als Common Practice in .Net. Was nützt ein schönes Dispose wenn niemand es aufruft? Genau dafür ist dieses Pattern gedacht.
Sorry, habe mich (mal wieder) nicht genau genug ausgedrückt.
Ich meinte sowas:
class Miep : IDisposable
{
SomeIDisposableImplementation mööp;
public void Dispose()
{
mööp.Dispose();
}
}
Es macht hier absolut gar keinen Sinn noch einen Finalizer zu haben, wenn SomeIDisposableImplementation schon einen mitbringt.
Und das dürfte hauptsächlich der Fall sein. Unmanaged resources, die nicht bereits in BCL/3rd-Party Klassen gekapselt sind, habe ich selbst fast nur in unsafe code. Oder ich habe sie selbst schon soweit gekapselt damit man sie an mehreren Stellen sicher benutzen kann.
Original von talla
@ kleines_eichhörnchen
Kleiner Verbesserungsvorschlag: Dein Dispose folgt nicht dem von MS vorgeschlagenen Pattern für .Net wenn du keinen Finalizer implementierst.
Etwas OffTopic...
Sehr oft, eigentlich fast immer, impementiert man IDisposable um dem Konsumenten ein determinstisches Freigeben von direkt und indirekt benutzten unmanaged Resources zu ermöglichen. Der zweite Grund ist, dass man keine Finalizer in einem GC Sweep haben möchte.
Wenn ich also ein Feld habe, dass IDisposable implementiert bin ich gut beraten selbst IDisposable zu implementieren damit der Konsument meiner Klasse den Finalizer dieses Feldes umgehen kann. Die Klasse selbst braucht natürlich keinen, wenn die Klasse hinter dem Feld schon einen hat.
Es ist eher good practice so wenig wie möglich Finalizer zu benutzen, wenn überhaupt, IMHO.
Original von mutzel
da ich aus der vergangenheit (mit BCB 6) mitbekommen hab das das mit der threadsicherheit nur schwer nachzuvollziehen ist würde ich gern wissen ob das VS2005 jede nicht threadsichere aktion bemerkt oder ob das nur bei zugriffen auf die GUI funktioniert?
Weder SWF noch die VCL sind thread safe. Du musstest also auch schon bei der VCL deinen Code durch Synchronize absetzen.
In SWF wird das durch die Invoke Methode gelöst, die jedes Control besitzt.
Original von feadur
bei genauer messung (inkl. ladevorgang) müsste das c# programm eigentlich noch langsamer sein, da zuerst der CLI Code vom Jitter in Maschinencode umgewandelt werden muss, was bei VB 6 nicht der Fall ist (da nativer Code).
Seit wann ist JIT-compiled Code langsamer als eine interpretierte Skriptsprache?
Und seit wann darf sich eine interpretierte Skriptsprache "nativer Code" nennen?
Solange du Code benutzt, der in der VB RTL enthalten ist (welche nunmal nicht in VB geschrieben sein kann ), und nur wenig eigenen Code "drumrum" hast, sollte die Peformance annähernd gleich sein.
Da können dich sogar die Sicherheitsprüfungen von .Net in den Hintern beißen, da ein Call etwas mehr kostet als ein Call von VB in eine importierte (aka wirklich native) Funktion.
Original von herbivore
wenn ich QuotedStr "Die Funktion gibt für einen String die entsprechende Version in Anführungszeichen zurück." richtig verstanden habe:
str = "\"" + str + "\"";
oder
str = String.Format ("\"{0}\"", str);
Hi hebivore,
nicht ganz. Delphis QuotedStr würde eher so aussehen:
Ich muss aber noch einen Fall sehen, in dem diese Funktion benutzt wird, der nicht gegen das Prinzip verstösst möglichst keine Werte in SQLs einzubetten.
Original von svenson
Solange dieses rotte Zeugs nicht aus dem IE veschwindet, fasse ich das Ding nicht mehr an. Nutzen ist gleich Null, und zugleich das gößte, denkbare Sicherheitsrisiko.
Ich fasse ihn auch nur unfreiwillig und indirekt an. Zum Beispiel in dexplore oder anderen Ecken in Anwendungen, die man trotz des IE Controls darin nicht einfach so umgehen kann (siehe BDS, VS, MMC,...).
Original von svenson
MS sollte mal Weisheit beweisen und Active Scripting für die Internet-Zone grundsätzlich nicht mehr zuzulassen. So aber haben sie die ständige Dresche einfach verdient.
Die Tatsache, dass OE eine Lücke im IE auslösen kann zeigt doch wieder sehr schön was ein COM/ActiveX verseuchter "Browser" bedeutet.
Das Ding sollte ein Browser sein, kein Remote-AppServer.
Natürlich ist mir klar, dass MS auf die Art hofft Abhängigkeiten auf ihr Betriebssystem zu erzeugen. Das kann man auch irgendwo verstehen.
Aber warum zum Geier benutzen sie nicht ein Extra AddOn, das entartete, ActiveX-verseuchte Webseiten darstellen kann? Auf die Art könnte man wenigstens den Kern des IE als Browser benutzen.
Original von Lynix
Weder "Verweis aktualisieren" noch Verweis raushauen und neu einbinden funktionieren... Ich kriege immer noch den alten Stand der Reference.cs ... und das obwohl ich mich per LeechFTP vergewissert habe, dass der aktuelle Sourcecode auf dem Server liegt :-(
Was sagt denn das WSDL?
Zitat
Zum Thema Contract First Design :
Wie gesagt, es handelt sich nur um eine kleine Testanwendung, zum Ausprobieren mit Webservices unter .NET 2.0
Oki, dann mal etwas weiter ausgeholt...
Durch das setzen des WebMethod-Attributes hast du dem ASPX Host gesagt er soll sie für dich so verpacken, dass man sie von außen über eine SOAP Anfrage ausführen kann.
Damit das mit der neuen Version deiner Klasse geht muss der Service laufen (Das WSDL muss ja irendwo herkommen )
Bist du dir sicher dass du die aktuelle DLL auf dem Server hast bzw. wennn du das ASPX Modell von VS2005 benutzt: die neuen Source files?