Naja, implementierst Du halt das was Du brauchst.
Wenn man keine Operatoren oder Equals braucht, kann man's eben weglassen. Macht ja nicht in allen Fällen Sinn.
Ein paar ganz einfache Typen sind IMO schnell erstellt.
Um 200 Zeilen Code zu verbessern... naja - ich versuche solche Fragen eher allgemein zu betrachten. Wir wissen ja gar nicht, in welchem Zusammenhang der TE das braucht.
Meiner Erfahrung nach machen eigene Typen eigentlich immer Sinn, wenn man mit solchen Größen zu tun hat und das Programm nicht nur eben zum Lernen oder als Fingerübung dient.
Extra Datentypen halte ich auch für Weit über das Ziel hinaus, da diese dann auch nur jeweils eine Eigenschaft mit repräsentieren.
Viel zu viel Aufwand nur um eine Trennung der Konstruktor Parameter umzusetzen.
Wenn es nur um die Konstruktorparameter geht - vielleicht.
Aber normalerweise macht man ja auch noch irgendwas anderes mit diesen Daten bzw. Typen. Man erstellt ja nicht aus Spaß an der Freud irgendwelche Objekte.
Und dann ist Typsicherheit doch sicherlich wünschenswert.
Wie ich bereits schrieb, haben solche Typen auch viele weitere Vorteile. Ich kann dann zum Beispiel auch Operatoren wie +/- definieren und so sicherstellen, dass ich wohl ein Gewicht zu einem Gewicht addieren kann, nicht aber versehentlich ein Gewicht zu einer Dichte - Typsicherheit eben, mit allem was dazugehört.
Mag auch daran liegen, dass ich beruflich sehr viel mit verschiedenen physikalischen Größen zu tun habe - bei uns ist das dann durchweg mit solchen semantischen Typen umgesetzt und es bringt uns viele Vorteile und macht den Code verständlicher.
Da jetzt eigens neue Klassen zu erfinden, die dann auch einen Konstruktor haben, woraus sich dann Konstruktoren in Konstruktoren ergeben
...
Weil eigene Konstruktor-Konstruktor-Klassen zu erfinden ist numal aufwändig
das ist aber gar nicht das, worum es geht.
Bei meinem Ansatz z.B. ist das Ziel, Daten mit unterschiedlicher Semantik in unterschiedliche Typen zu packen. Gerade bei physikalischen Größen drängt sich mir persönlich diese Vorgehensweise geradezu auf.
Das Konzept ist auch nicht extra oder ausschließlich dafür da, verschiedene Konstruktoren bereitstellen zu können. Es steckt viel mehr dahinter, und das kann einem das Leben auch an vielen anderen Stellen erleichtern, da solche Typen eben wirklich universell einsetzbar sind.
Wenn man von Anfang an mit solchen semantischen Typen arbeitet, würde sich eine Frage nach den überladenen Konstruktoren in der Weise gar nicht stellen (weil z.B. ein Volumen eben keine Dichte ist).
mit eigenen Parameter-Typen zu arbeiten, welche dann auch ihre eigenen Fehler habe können und eigene Unit-Tests haben sollten
Würde ich so sehen.
Wenn Du das Spielchen mit den Einheiten machen willst, gibt es im Prinzip auch was für Unit Tests.
Wenn Du das nicht brauchst (immer in den gleichen Einheiten rechnest), reichst Du ja nur einen Wert weiter, da würden sich UnitTests damm IMO nicht wirklich lohnen.
Ob das der "beste" Weg ist sei mal dahingestellt, das muss jeder für sich selbst entscheiden. Es ist aber auf jeden Fall das, was ich persönlich dafür halte ;)
sorry, meine Edits haben sich da mit Deinem Post überschnitten.
NumericField habe ich rausgenommen (hatte zuerst eine Basisklasse gemacht, dachte dann aber, structs seien hier besser.
Zu sealed-Datentypen: Die structs von mir sind ja auch sealed... verhält sich genauso. Du baust ja eine Struktur, die den eigentlichen Wert wrappt, da ist es Dir egal ob sealed oder nicht.
also ich würde hier definitiv einzelne Datentypen bauen die die unterschiedliche Semantik abbilden.
Das eine ist nun mal ein Gewicht, das andere ein Volumen, und nur weil beide numerisch gemessen werden, sind sie noch lange nciht dasselbe -> warum dann also dem Code alles als double unterjubeln?
Im folgenden Beispiel gibt es eigene Typen für Gewicht, Volumen und Dichte. Die sind dann vollständig flexibel kombinierbar im Konstruktor, und biten zudem die Möglichkeit, sehr leicht mit unterschiedlichen Einheiten umzugehen (ich habe das beispielhaft beim Volumen mal gemacht).
Solche Typen sind dann im Gegensatz zu zusammengesetzten Initialisierungsobjekten auch völlig universell einsetzbar.
public class Koerper
{
#region privates
Volumen volumen;
Gewicht gewicht;
Dichte dichte;
#endregion
#region Constructors
public Koerper()
{
}
public Koerper(Dichte d, Volumen v)
{
dichte = d;
volumen = v;
}
public Koerper(Gewicht g, Volumen v)
{
gewicht = g;
volumen = v;
}
public Koerper(Dichte d, Gewicht g)
{
dichte = d;
gewicht = g;
}
#endregion
}
public struct Dichte
{
double _value;
public Dichte(double val)
{
_value = val;
}
// hier noch Factory- und Zugriffsmethoden (siehe Volumen)
}
public struct Gewicht
{
double _value;
public Gewicht(double val)
{
_value = val;
}
// hier noch Factory- und Zugriffsmethoden (siehe Volumen)
}
public struct Volumen
{
double _value;
public Volumen(double val)
{
_value = val;
}
// Factorymethoden um aus verschiedenen Einheiten zu erzeugen
public Volumen FromKubikzentimeter(double val)
{
return new Volumen(val / 1000000);
}
public Volumen FromLiter(double val)
{
return new Volumen(val / 1000);
}
public Volumen FromKubikmeter(double val)
{
return new Volumen(val);
}
// Zugriff über verschiedene Einheiten
public double Kubikzentimeter { get { return _value * 1000000; } }
public double Liter { get { return _value * 1000; } }
public double Kubikmeter { get { return _value; } }
}
Gruß, MarsStein
Edit: da war noch ein Fehler im Code...
und noch einer... die Factory-Methoden in Volumen hatten gar keine neuen Objekte erzeugt :( -> korrigiert
das liegt daran, dass ein Admin generell auch Moderationsberechtigungen hat (und diese für gewöhnlich auch wahrnimmt).
Zusätzlich gibt es dann noch einige Moderatoren, die aber nicht über Admin-Rechte verfügen.
wie wird der Messwert denn genau ausgegeben? "ein kleinses digitales Display" -> sowas wie eine Digitale Uhr?
Wenn's nichts grafisches ist, dann kommst Du vielleicht mit OCR weiter. Also im Prinzip was Mr. Sparkle auch schon geschrieben hat (Texterkenung). Tesseract ist da eine gute OSS.
--> NotImplementedException :-) Ansonsten sehe ich das auch so wie Du.
...und dann die nicht unterstützte Methode am besten explizit implementieren, dann kann sie nur über das Interface aufgerufen werden (nicht mit der normalen ungecasteten Klasseninstanz).
Du könntest statt einer RTB ein WebBrowser-Control verwenden. Damit lässt sich das recht leicht erledingen. Die Boxen wären dann normale <div>...</div>.
Schau mal in Textfeld mit Formatierung und klickbarem Text, ist nicht genau Dein Anwendungsfall, aber Du kannst ähnlich vorgehen.
die Syntax mit dem $-Zeichen vor dem String ist ein neues Feature von C# 6 und gibt es erst seit VS 2015. Wenn das bei Dir nicht klappt, bleib bei dem String.Format.
Zitat
leider weiss ich nicht was man dafür benutzt "if contains" kenne ich aus java ka obs das in c gibt
Falls Du sie doch brauchst, kannst Du auch mal einfache Hochkommata statt der doppelten Anführundzeichen probieren: "Extended Properties='Access 12.0 Xml;HDR=Yes'" <-- dass aber HDR=YES bei der .accdb sinnvoll ist, glaube ich eigentlich nicht, und ob es sich um ein Xml-Format handelt, kann ich nicht sagen.
Du trägst beim Auslesen nur Werte der Knoten in die Liste ein, für die auch mindestens ein Folgeknoten (Left oder Right) existiert.
Existieren beide Folgeknoten, trägst Du dafür den Wert des aktuellen Knotens doppelt ein...
danke für den Hinweis, Gü. Das kannte ich so nicht. Allerdings scheinen die Möglichkeiten da eher begrenzt zu sein.
Sowas wie "warte bis zum Abschluss der laufenden Aufgabe und versuche es dann wieder" habe ich jedenfalls auf die Schnelle nicht gefunden - eher nur solche Einstellungen, die festlegen, wann eine laufende Aufgabe abgebrochen werden soll/darf.
Hab jetzt allerdings gerade nur Win7 zur Hand, vielleicht hat sich da ja mittlerweile was geändert. Oder ich bin einfach blind
falls Du mit einem Timer oder dem TaskScheduler arbeitest, wäre es noch wichtig, wie lange Deine Bearbeitung/Konvertierung dauert.
Behalte auf jeden Fall im Hinterkopf, was passiert, wenn die Bearbeitung länger dauert als das Zeitintervall.
Bei einem Timer kannst Du den immer nur einmal ticken lassen und erst wieder aktivieren, wenn die Bearbeitung durch ist - ähnlich kannst Du es auch bei einem Dienst selbst steuern.
Der TaskScheduler bietet Dir diese Möglichkeit nicht.
Kannst Dir ja mal den dort verlinkten Thread auf Stackoverflow anschauen. Es läuft allerdings auch dort darauf hinaus, das Focusable auf true gesetzt wird, also letztlich Dein bereits gefundener Workaround.
Eine andere Lösung wüsste ich jetzt auch nicht.
LaTino hat's richtig gelöst und ist somit an der Reihe :)
Hier noch mal meine eigene Lösung:
checked
{
for (int i = min, end = 0; end == 0; end = (max == i) ? 1 : (++i - i))
action(i);
}
Zitat von LaTino
Code-Teile zum Auf- und zuklappen im Forum wärn cool ;).
Das Feature gibt es doch - hab es seinerzeit selbst hier für's Forum implementiert... Wenn Du Javascript erlaubst, gibt es neben dem Titel "C#-Code" so ein "-" zum zu- bzw. "+" zum wieder aufklappen :)
Sobald ich es weg lasse kommt in der textBox => n. def.
Das und die Fehlermeldung deuten beide darauf hin, dass irgendwo double.NaN ensteht in der distance-Funktion.
Also prüfe mit
if(!double.IsNaN(inkm))
textBoxLaenge.Text = Convert.ToDecimal(inkm).ToString("0.00");
else
{
// hier ist was schiefgelaufen.
// Koordinaten ansehen und beim nächsten mal diese speziellen Koordinaten per if-Abfrage
// vor dem Aufruf abfangen, Haltepunkt setzen, durchsteppen, gucken was passiert.
}
Gruß, MarsStein
Edit: hatte ich doch das ! vor der Bedingung vergessen... wie im richtigen Leben ;)
@herbivore: Allen Deinen Aussagen zu der Aufgabe stimme ich vollumfänglich zu :)
@all: herbivores Ansatz mit einer zweiten Schleifenvariable ist auch schon der wichtigste Tipp.
Hier noch einer:
Die Variable, gegen die die Bedingung geprüft wird, ist nicht unbedingt die, die inkrementiert wird. Bei meiner eigenen Lösung würde ich theoretisch bei der zweiten Variablen mit einem bool auskommen, das ist allerdings syntaktisch nicht möglich.
das Programmierspiel ist ja fast schon in Vergessenheit geraten... hier trotzdem nochmal eine kleine Aufgabe zum Grübeln.
Gegeben ist folgende statische Methode:
[csharp]
public static void Loop(int min, int max, Action<int> action)
{
if (min > max)
throw new ArgumentException("min must be lesser than or equal max");
checked
{
for (int i = min /*hier Euer übriger Schleifenkopf*/)
action(i);
}
}
[/csharp]
Die Grenzen [tt]min[/tt] und [tt]max[/tt] sind beide inklusive.
Die Methode soll für jeden [tt]int[/tt] im übergebenen Bereich einmal die übergebene [tt]action[/tt] ausführen (wenn [tt]min == max[/tt] darf die Action also nur einmal ausgeführt werden).
[B]Füllt den Schleifenkopf der [tt]for[/tt]-Schleife so, dass alle Eingaben von [tt]int.MinValue[/tt] bis [tt]int.MaxValue[/tt] korrekt verarbeitet werden.
Es darf nur der Schleifenkopf (innerhalb der Klammern, wo der Kommentar steht) verändert werden!![/B]
Beachtet, dass die Schleife in einem checked-Block steht, Überläufe also nicht erlaubt sind.
// s und t
double s = d2 / d1;
double t = d3 / d1;
An der Stelle ist das, was in s und t steht, wieder ein ganzzahliger Wert, weil Du in der Rechenoperation nur mit Integern (d1, d2, d3) rechnest.
Sattdessen könntest Du d1, d2, d3 direkt als double deklarieren, oder eben einen der Werte in der Berechnung auf double casten:
//-----------ENTWEDER SO------------:
double d1 = x1 * y2 - y1 * x2;
double d2 = x3 * y2 - y3 * x2;
double d3 = x1 * y3 - y1 * x3;
// s und t
double s = d2 / d1;
double t = d3 / d1;
//-----------ODER SO------------:
double s = d2 / (double)d1;
double t = d3 / (double)d1;
da die Registry.GetValue-Methode nur einen String als Namen für den Key annimmt, wirst Du damit vermutlich immer nur auf dem lokalen Rechner landen.
Benutze zum Auslesen/Setzen der Werte die GetValue- und SetValue-Methoden des RegistryKey-Objektes selbst.
In dem Beispielcode in der Doku wird das auch so gemacht - bitte in Zukunft die etwas genauer lesen ;)
Deine List<string[]> sowie die enthaltenen string[] sind ohnehin schon Referenztypen, es wird also nur die Referenz (kopiert und) übergeben, nicht die Daten. Da brauchst Du dann nichts weiter machen.
Ist das Netzwerk richtig konfiguriert (Netzerkerkennung, Firewall etc.)?
laufen auf beiden Rechnern die Dienste "Remoteregistrierung" und "Windows-Remoteverwaltung"?
Hast Du mit dem Konto, unter dem Du das versuchst, Admin-Rechte auf dem Remoterechner?
Stecken die beteiligten Rechner eigentlich in einer Domäne? Bedenke jedenfalls, dass Du mit RegistryHive.CurrentUser auf einem Remoterechner nicht unbedingt da landest, wo Du willst.
Es läuft darauf hinaus, entweder einen Dienst zu schreiben der auf dem Remotecomputer läuft, und einen Client, der mit dem Dienst kommuniziert, oder aber den vorhandenen Remoteregistrierungs-Dienst zu nutzen und Remoteadministration zu aktivieren.
mein zweiter Vorschlag wäre in dem Beispiel, der äußeren Border den Background Red zu geben und dem Textblock (oder einem rechteckigen Element, das Du noch unter den Textblock packst) den Backgound SCB.Training.Item. Die beiden inneren Borders brauchst Du dann nicht mehr.
Das müsste dann in etwa so aussehen, wie Du es haben willst - das funktionert halt nur nicht, wenn der Bereich hinter dem Text transparent sein soll.