Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

1

03.01.2011, 21:11

[C#] "schönere" Lösung für diesen Code?

Hallo,

ich hab hier eine klitzekleine, einzeilige Funktion geschrieben, die trotzdem irgendwie bäh ist. Und zwar tut die nichts anderes als generisch zwei Zahlen zu dividieren. Damit wären wir beim Problem. Das ist nämlich bisher so gelöst:

C#-Quelltext

1
2
3
4
public static T div(T num1, T num2)
{
    erg=typeof(T).GetMethod("operator/").Invoke(num1, new object[]{num2});
}


Ich tue im Prinzip nichts anderes als zu überprüfen, ob der übergebene Typ den Operator / unterstützt und diesen dann aufzurufen. Gibt es da nicht eine schönere und sicherere Lösung (Wunschdenken: Ein Interface, was Unterstützung von mathematischen Funktionen definiert, zum Beispiel) als diese?

TrommlBomml

Community-Fossil

Beiträge: 2 117

Wohnort: Berlin

Beruf: Software-Entwickler

  • Private Nachricht senden

2

03.01.2011, 21:13

welchen anwendungsfall hat das? ansonsten würde ich einfach für jedes Objekt den Divisionsoperator überladen; Warum sollte man dafür ein generisches Interface benötigen?

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

3

03.01.2011, 21:21

Ich hatte keine Lust, das Teil für jeden numerischen Datentypen (und das sind nun mal viele) zu überladen. Diese Lösung hier ist sowohl von der Performance als auch von der Stabilität her (wenn der /operator nicht geht, fliegts einem um die Ohren) nicht so der Burner. Insofern wäre es schön, das ganze nicht generisch zu haben, sondern halt als z.B. Interface, das die mathematischen Operatoren vorschreibt oder so (denn auf object kann man den logischerweise auch nicht anwenden). Wäre es vielleicht sinnvoll und möglich, ein solches Interface zu schreiben?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

03.01.2011, 21:53

Ich tue im Prinzip nichts anderes als zu überprüfen, ob der übergebene Typ den Operator / unterstützt

Eigentlich überprüfst Du da gar nichts. Wenn ich 'nen String als T übergebe, dann bekommt man eine NullPointerException und fertig.

"Vernünftig" wäre z.B.:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
static bool IntegerFunction<T>(T value) where T : struct {
  if (typeof(T) != typeof(Int16)  &&
      typeof(T) != typeof(Int32)  &&
      typeof(T) != typeof(Int64)  &&
      typeof(T) != typeof(UInt16) &&
      typeof(T) != typeof(UInt32) &&
      typeof(T) != typeof(UInt64)) {
    throw new ArgumentException(
      string.Format("Type '{0}' is not valid.", typeof(T).ToString()));
  }

  // Rest of code...
}

Muss man nur entsprechend erweitern.

Gefunden hier: http://stackoverflow.com/questions/32664…r-only-integers

Leider ist das nur ein Runtime-Check.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »BlueCobold« (03.01.2011, 22:03)


5

03.01.2011, 22:37

1. kommts mir nur so vor, oder soltle der Rest of Code nach die schließende klammer von struct?
Leider ist das nur ein Runtime-Check.

2. was anderes gibts in C# meines wissens ja auch nicht, jedenfalls nicht, wenn man bei Generics solche hacks veranstaltet - ein vergleichbarer Hack, um bei C++-templates constraints zu simulieren, ist dagegen compile-time...

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

03.01.2011, 22:43

Ich hatte keine Lust, das Teil für jeden numerischen Datentypen (und das sind nun mal viele) zu überladen.

Sind es wirklich so viele dass du lieber auf hässliche Runtime checks baust als maximal 13 (vermutlich weniger) Einzeiler zu schreiben!?
Wofür genau brauchst du das überhaupt!?

Diese Lösung hier ist sowohl von der Performance als auch von der Stabilität her (wenn der /operator nicht geht, fliegts einem um die Ohren) nicht so der Burner.

Was anderes ist ja wohl auch nicht zu erwarten!?


Insofern wäre es schön, das ganze nicht generisch zu haben, sondern halt als z.B. Interface, das die mathematischen Operatoren vorschreibt oder so (denn auf object kann man den logischerweise auch nicht anwenden). Wäre es vielleicht sinnvoll und möglich, ein solches Interface zu schreiben?

Ich bin mir sogar sicher dass es eine bessere Lösung gibt. Ich schlage vor du beschreibst mal was du eigentlich genau tun willst...

verrueckt1993

Frischling

  • »verrueckt1993« ist der Autor dieses Themas

Beiträge: 85

Beruf: Informationstechnischer Assistent Fachrichtung AE, 2. Jahr

  • Private Nachricht senden

7

03.01.2011, 22:54

@dot:

Naja, 13 Einzeiler pro Memberfunktion.... ich hatte nicht so die Lust, das 13fache an Code zu tippen^^

Okay, ich gebe ein Beispiel. Nehmen wir mal an, man will eine Physikengine schreiben, die sich nicht auf einen Datentyp (z.B. Double) beschränkt (wäre aus Performancegründen ganz praktisch, z.B. ein int zu verwenden, wo man eigentlich gar kein double braucht). Aus performancetechnischer Sicht müsste man dann logischerweise überladen, was allerdings nicht so gut zur programmierertypischen Schreibfaulheit passen würde. Also dachte ich, ein Generic wäre hier ganz sinnvoll. Hier stößt man dann auf das Problem mit den mathematischen Operatoren, die von einem generischen Datentyp logischerweise nicht unterstützt werden. Problem hier ist, dass alle numerischen Datentypen in .NET von Object ableiten und es keinen Typ "dazwischen" gibt, der garantiert, dass diese Operatoren unterstützt werden.

@PCShadow:

dumm nur, dass im Threadtitel C# steht und nicht C++...

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

8

03.01.2011, 23:19

Ok, also wenn du mich fragst: Wenn du Performance willst dann lass das. Es gibt rein im Hinblick auf Effizienz keinen Grund int zu verwenden, wenn dann vielleich wegen Fixkommapräzision und solchen Dingen. Und das macht eben auch nur in gewissen Fällen Sinn. Überladen wäre hier also auch eher kaum die Lösung. Du kannst dir natürlich selber Zwischentypen basteln die ein bestimmtes Interface implementieren und über Constraints deine Generics gegen dieses Interface coden. Inwiefern der JIT da dann inlinen etc. kann sodass das Ganze am Ende auch nur irgendwo in die Nähe von etwas kommt was man als Performance bezeichnen könnte kann ich dir mangels Erfahrung nicht vorhersagen. Ich denke du solltest dir an dieser Stelle wirklich die Frage stellen ob du von der Generizität hier auch nur irgendwas hättest. Ich meine, heutzutage ist doch eh praktisch alles float basiert bis auf einige Ausnahmen wo man vielleicht wegen Genauigkeitsfragen auf Fixkomma setzt. Und wenn du wirklich an den Punkt kommst wo die reine Arithmetikperformance zum Problem wird dann wird es sowieso eher schwer sein mit C# eine Lösung zu finden.

Werbeanzeige