| 

.NET C# Java Javascript Exception

3
Hallo,

ich möchte ein Byte Array unregelmässig mit Werten auffüllen. Ermittelt werden muss immer wieder neu, ob ein Element bereits besetzt ist oder nicht. Mögliche Werte sind 0 - 255. Wenn nun aber ein Element den Wert 0 beinhaltet, wie stelle ich dann fest, ob es beteits gesetzt wurde? Wenn der Array festgelegt wird, enthalten alle Elemente 0.

Muss ich in diesem Fall ein bool Array nebenherlaufen lassen, oder gibt es eine andere einfachere Möglichkeit das festzustellen? Es muss unbedingt ein Byte Array sein.
News:
30.03.2014
SaBra 35 1 4
Die Frage ist doch, was soll passieren, wenn ein Element besetzt ist oder nicht (bei Zuweisung und Zugriff) und warum es ein Byte-Array sein muss (byte?[] ist nun mal kein Byte-Array)
jeff 09.04.2014
1
Magst Du mir erklären warum Du meinst, dass diese Fragen wichtig sind?

Aus meiner Sicht ist es irrelevant was SaBra damit vor hat, denn sie/er kann so lange nicht drauf reagieren bis festgestellt wird, ob der Wert 0 ungesetzt oder eben 0 bedeutet.

Und es wird wohl ein Byte-Array sein müssen weil es entweder eine Vorgabe gibt oder man eben kein Integer-Array mit eingehender Platzverschwendung haben möchte. Byte? ist sicher näher an Byte dran, als ein Iteger. Mit -1 zu arbeiten ist u.U. keine dauerhafte Lösung, denn es kann ja durchaus sein, dass die Anforderungen sich mit der Zeit verändern
Jens Duczmal 11.04.2014
Es ist u.a. eine Frage des Aufwands und der Lesbarkeit des Quellcodes. Anstatt des Hantierens mit .HasValue, .Value und explizitem Konvertieren hätte ich vermutlich eine Lösung mit einem Dictionary<int, byte> bevorzugt. Je nach Antwort auf die Fragen hätte man direkt damit arbeiten können oder noch eine Wrapper-Klasse ggf. mit Indexer genutzt.
jeff 11.04.2014
@jeff: Da HasValue nicht so gut anzukommen scheint, habe ich noch eine weitere Lösung zugefügt, die mit einem byte-Array arbeitet. Im Gurunde - wie es gefordert wurde...!?
Falkner 11.04.2014
Hier hat sich ja viel getan. War einige Zeit nicht hier. Also Dictionary ist unchbrauchbar für meine Sachen. Im Notfall werde ich das mit HasValue machen. Aber ich werde die neue Lösung von Falkner erst mal testen. Wenn die funktioniert, liegt sie näher an meiner Wunschvorstellumg.
SaBra 11.04.2014
@SaBra: Freut mich, dass du meine weitere Lösung probieren möchtest. Wenn sie dir gefällt, geht der "Ruhm" jedoch auf dich zurück. "Ein bool-Array läuft nebenher"!!! Ich habe deine Idee (s. deine Frage) nur umgesetzt.
Falkner 12.04.2014
@SaBra: Schade, dass Du nicht näher erklärst, warum Dictionary unbrauchbar ist - über einen Wrapper mit Indexer sieht das exakt so aus, wie bei einem Byte-Array. Einzig beim Zugriff auf das Gesamt-Array müsste man sich eine Kopie erzeugen. Aber wie relevant das ist, kann ohne nähere Informationen nicht beurteilt werden.
jeff 22.04.2014
3 Antworten
3
Du musst dein Array als Nullable definieren. Siehe mein Beispiel:

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
byte?[] byteArray = new byte?[20];
byteArray[3] = 2;
byteArray[10] = 1;
byteArray[17] = 50;
byteArray[18] = 0;
byteArray[1] = 0;

for (int i = 0; i < byteArray.Length; i++)
{
if (((byte?)byteArray[i]).HasValue)
Console.WriteLine(String.Format("Bytearray {0} ist belegt. Wert={1}", i, byteArray[i]));
}
Console.ReadKey();

// Aber Achtung, möchtest Du beispielswiese einer normalen byte Variablen einen Wert aus dem Array zuweisen, welche keinen Wert enthält,
// so erhälst Du beim Zugriff einen Fehler
byte einByte = (byte)byteArray[12]; // Dies wird eine exception auslösen

// Du kannst entweder mit

byte einByte2 = 0;
if (byteArray[12].HasValue)
einByte2 = (byte)byteArray[12];
// darauf zugreifen, oder noch einfacher mit:

einByte2 = byteArray[12].GetValueOrDefault(0);

// GetValueOrDefault(0) gibt den Wert, falls vorhanden zurück, oder als Default die angegebene 0
}
}
}
30.03.2014
JEwen 2,7k 5
Danke f. dein Code Beispiel. Ich habe es versucht und erhielt dabei die folgende Fehlermeldung:

Eine Konvertierung vom Typ 'byte?[]' in 'byte?' ist nicht möglich. (CS0030)

Wie kann man das abstellen?
SaBra 30.03.2014
3
Das Sample von JEwen bietet dir mehrere Möglichkeiten. Bei mir funktioniert:

public NurTest()
{
byte?[] byteArray = new byte?[20];
byteArray[3] = 2;
byteArray[10] = 1;
byteArray[17] = 50;
byteArray[18] = 0;
byteArray[1] = 0;

if (byteArray[0].HasValue)
Console.WriteLine("Ja");
else
Console.WriteLine("Nein");
}
Falkner 30.03.2014
1
Dank an alle Helfer und Mithelfer. Jetzt hab ich das verstanden. Und es geht bei mir jetzt auch fehlerfrei.
SaBra 30.03.2014
1
Freut mich dass es jetzt funktioniert. Mach dem Jens doch auch noch ein +1 rein, denn er hat ja eigentlich die richtige Lösung bereits aufgezeigt.
JEwen 30.03.2014
2
Hab ich gemacht.
SaBra 30.03.2014
1
Dankeschön :)
Jens Duczmal 31.03.2014
@JEwen: Einige Lösungsmöglichkeiten deines Codes scheinen nicht zwischen "0" und "nichts" unterscheiden zu wollen. Oder sehe ich da was falsch? Mit Falkners Snippet geht das. Oder habe ich was falsch verstanden?
Wittgenstein 10.04.2014
@Wittgenstein: Wie Falkner schon schrieb, mehrere Möglichkeiten. Mir ging es hauptsächlich darum ihm zu zeigen wie er mit Nullable Datentypen arbeiten kann. Nein, ein explizites Beispiel auf "0" und Nichts war jetzt nicht drin, denke aber, dass dem Fragesteller mit dem Beispielcode ein möglicher Lösungsweg aufgezeigt wurde.
JEwen 10.04.2014
3
Ich weiss es gerade nicht aus dem Kopf, aber es müsste auch für Byte den Subtyp Nullable geben. Du kannst dann über .HasValue abfragen ob ein Wert gesetzt ist und so zwischen Null und 0 unterscheiden.
30.03.2014
Jens Duczmal 2,6k 1 3 9
Ich bekomme dann die folgende Fehlermeldung:

'byte' enthält keine Definition für 'HasValue', und es konnte keine Erweiterungsmethode 'HasValue' gefunden werden, die ein erstes Argument vom Typ 'byte' akzeptiert.
SaBra 30.03.2014
1
Da dieses Thema noch weiter kommentiert wird, habe ich noch eine Lösung zusätzlich eingebracht. Weil es sich um ein byte-Array handeln soll, habe ich eine Lösung gebastelt, die Einfügungen brav mit einem solchen umsetzen kann.

Mit dem nachfolgenden Code-Beispiel können einem Array einzelne Werte übergeben werden. Dabei wird getestet, ob ein Feld be- oder unbesetzt ist. Wenn ein Feld bereits einen Wert enthält, wird es nicht überschrieben. Die 0 wird ebenfalls als Wert festgestellt, wenn eine enthalten ist. Zu beachten ist, dass nur die Methode InsertValue für die Array-Auffüllung genutzt werden darf.

Die Mini-Klasse ArrayClass kann bspw. für Delete und andere Methoden auf einfache Weise ergänzt werden, wenn diese benötigt werden. Zumindest ist meine Lösung eine Alternative zu HasValue.

Viel Spass damit!


class Program
{
public static void Main(string[] args)
{
byte[] byteArray = new byte[20];
bool[] hv = new bool[byteArray.Length];
byte[] newBytes = {0, 244, 100, 89, 77, 33};

/*Array mit Testwerten füllen*/
ArrayClass.InsertValue(newBytes[0], 0, byteArray, hv);
ArrayClass.InsertValue(newBytes[4], 5, byteArray, hv);

ShowArray(byteArray);

/*Weil auf Index 0 bereits d. Wert 0 steht, wird nicht einfefügt*/
if(ArrayClass.InsertValue(newBytes[0], 0, byteArray, hv))
Console.WriteLine("\n\nWert wurde eingefügt!");
else
Console.WriteLine("\n\nWert konnte nicht eingefügt werden. " +
"Das Feld ist bereits besetzt!");

if(ArrayClass.InsertValue(newBytes[2], 1, byteArray, hv))
Console.WriteLine("\n\nWert wurde eingefügt!");
else
Console.WriteLine("\n\nWert konnte nicht eingefügt werden. " +
"Das Feld ist bereits besetzt!");

ShowArray(byteArray);

Console.Write("\n\nPress any key to continue . . . ");
Console.ReadKey(true);
}

/* Nur für die Ausgabe erforderlich*/
private static void ShowArray(byte[] byteArray)
{
Console.WriteLine();
for(int x = 0; x < byteArray.Length; x++)
Console.Write(byteArray[x].ToString() + " ");
}
}


internal static class ArrayClass
{
internal static bool InsertValue(byte v, int pos,
byte[] b, bool[] hv)
{
if(hv[pos])
return false;
else
{
b[pos] = v;
return (hv[pos] = true);
}
}
}


Oder:

class Program
{
public static void Main(string[] args)
{
byte[] byteArray = new byte[20];
bool[] hv = new bool[byteArray.Length];
byte[] newBytes = {0, 244, 100, 89, 77, 33};

/*Array mit Testwerten füllen*/
InsertValue(0, newBytes[0], byteArray, hv);
InsertValue(5, newBytes[4], byteArray, hv);

ShowArray(byteArray);

/*Weil auf Index 0 bereits d. Wert 0 steht, wird nicht einfefügt*/
if(!HasValue(0, hv))
{
InsertValue(0, newBytes[0], byteArray, hv);
Console.WriteLine("\n\nWert wurde eingefügt!");
}
else
Console.WriteLine("\n\nWert konnte nicht eingefügt werden. " +
"Das Feld ist bereits besetzt!");

if(!HasValue(1, hv))
{
InsertValue(1, newBytes[2], byteArray, hv);
Console.WriteLine("\n\nWert wurde eingefügt!");
}
else
Console.WriteLine("\n\nWert konnte nicht eingefügt werden. " +
"Das Feld ist bereits besetzt!");

ShowArray(byteArray);

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}

internal static bool HasValue(int pos, bool[] hv)
{
return hv[pos];
}

internal static void InsertValue(int pos, byte v, byte[] b, bool[] hv)
{
b[pos] = v;
hv[pos] = true;
}

/* Nur für die Ausgabe erforderlich*/
private static void ShowArray(byte[] byteArray)
{
Console.WriteLine();
for(int x = 0; x < byteArray.Length; x++)
Console.Write(byteArray[x].ToString() + " ");
}
}
11.04.2014
Falkner 795 3 9
Falkner 795 3 9
@SaBra: Hab dir noch eine Alternative gebastelt!
Falkner 11.04.2014
Also ich hab hin und her überlegt und werde deine Lösung nehmen. Ich habe beschlossen deine Klasse mit meinen Funktionen zu erweitern. Das ist zwar etwas aufwendiger, aber letztendlich erspare ich mir Runtricksereien, die mit HasValue nötig wären. Danke!
SaBra 13.04.2014
@SaBra: Bitte! HasValue ist leider für so einige Einsätze etwas unhandlich.
Falkner 13.04.2014
Für mich ist ein Sprachfeature (nullable Types) wesentlich handlicher und verständlicher als eine Implementierung, bei der ich auf einmal zwei 'ref' Parameter brauche. Mag mein persönlciher Geschmack sein, aber Nullables finde ich wesentlich eleganter als 'ref' Parameter.
ffordermaier 13.04.2014
@ffordermaier: Es ist nicht zwingend nötig, ref zu benutzen, nicht einmal die Klasse...! Die betreffende Methode kann auch einfach genutzt werden. Niemand soll hier zum "BÖSEN" Wort "ref" gezwungen werden :-)
Falkner 13.04.2014
@ffordermaier: Ich habe meiner Antwort eine weitere Möglichkeit ohne "ref" zugefügt! :-)
Falkner 14.04.2014
Vielleicht ist es ja wirklich schon zu spät, aber ich sehe auch in der ersten Version keine Notwendigkeit für ref - das müßte auch ohne kompilieren. Das eigentliche Problem ist, dass ArrayClass keine Hoheit über seine Daten hat und sie ständig von außen hereingereicht bekommen muß. Mehr Anti-OO geht eigentlich nicht.

Und warum jetzt
HasValue(1, hv)
in irgendeiner Weise besser oder handlicher sein soll als
arrayOfNullableBytes[1].HasValue()
erschließt sich mir auch nicht.

Ansonsten kann ich mich nur ffordermaier anschließen. Der Code ist für mich ein Kandidat für http://thedailywtf.com
Matthias Hlawatsch 14.04.2014
@Matthias Hlawatsch: ... kleinlaut... ich habe Mist gebaut und bin über die Anspielung v. ffordermaier nicht gestolpert. Ich habe den Code noch einmal editiert. Ich hoffe, da sind jetzt keine Fahler mehr drin! Vielen Dank für deine Zeilen!!!

Ich wollte led. eine Alternative zu HasValue bieten. Der Vorsatz der Verbesserung war nicht gemeint.
Falkner 14.04.2014

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH