Permalänk

C# Addera m.h.a. generics

Hur kan jag addera två genric typer i en metod?

T.ex. i följande enkla exempel vill jag casta en sträng till en viss typ och addera ihop med ett värde av samma typ.

Detta genererar naturligtvis ett kompileringsfel eftersom operatorn "+" inte är definerad:

int testInt = Testing<int>(5); decimal testDecimal = Testing<decimal>(5.0M); private T Testing<T>(T increment) where T: struct { T parameterValue = (T)Convert.ChangeType("12345", typeof(T)); return parameterValue + increment; // <-- compiling error }

Visa signatur

"Mies saa kaatua mutta ei karata." -- Adolf Ehrnrooth IR 7, Äyräpää 1944.

Permalänk
Medlem

Problemet är att T är generell, och kan vara precis vad som helst. Vad ska den göra om du skriver ListBox ny = Testing<ListBox>(minFinaListBox);

Permalänk
Medlem

Du skulle kunna kolla vilken typ T är och hantera alla taltyper, alltså double, int, float, decimal m.fl.
Men förklara vad du ska med detta till...? Vad är syftet?

Permalänk
Medlem

I exemplet ovan så är det visserligen en 'constraint' till typen struct.
Eftersom operator överlagring alltid görs som statiska metoder* finns de inte i ett färdig interface. Annars hade du naturligtvis kunnat använda ett interface som constraint vid metoden som tar en generic typ.

Vad är det du är ute efter ?

Typo: klasser -> metoder

Permalänk
Skrivet av Sir. Haxalot:

Problemet är att T är generell, och kan vara precis vad som helst. Vad ska den göra om du skriver ListBox ny = Testing<ListBox>(minFinaListBox);

Exakt. Men Listbox är ingen struct:

... ... where T: struct ...

Problemet är bara att struct inte räcker, eftersom den inte har operatorn "+" och vad jag vet så finns det heller ingen datatyp där detta stämmer. Så då borde man lösa det på annat sätt, men frågan är hur?

Visa signatur

"Mies saa kaatua mutta ei karata." -- Adolf Ehrnrooth IR 7, Äyräpää 1944.

Permalänk
Medlem

Du skulle ju kunna använda overloads, d.v.s. många funktioner med samma namn fast olika innehåll beroende på datatype

int testInt = Testing(5); decimal testDecimal = Testing(5.0M); private int Testing(int increment) { int parameterValue = (int)Convert.ChangeType("12345", typeof(int)); return parameterValue + increment; // <-- compiling error } private decimal Testing(decimal increment) { decimal parameterValue = (decimal)Convert.ChangeType("12345", typeof(decimal)); return parameterValue + increment; // <-- compiling error }

Permalänk
Medlem

Så vad är det du är ute efter?

Permalänk
Skrivet av zoomster:

Så vad är det du är ute efter?

Jag har en tabell i en databas för parametrar som innehåller tre fält: Namn, värde och datatyp. Alla fält är strängar. Jag vill då skapa generella metoder som läser och uppdaterar tabellen.

Ex)

ProductCode 10001 System.Int32 PackageId 9876543210 System.Int64 Test 12345 System.Int32

Datatypen används för att validera att man använder rätt datatyp för varje parameter och för att kunna konvertera till rätt typ.

Jag har lyckats göra generella metoder för alla fall, förutom då jag ska uppdatera parametrarna (i praktiken addera 1 för att hålla "nästa tillgängliga nummer"). Alltså något i stil med:

T PopParameter<T>(string parameterName, T increment);

Metoden returnerar alltså värdet i tabellen och uppdaterar sedan värdet med 'increment'.

Och nej, string är ingen struct...

Visa signatur

"Mies saa kaatua mutta ei karata." -- Adolf Ehrnrooth IR 7, Äyräpää 1944.

Permalänk

Den vanligaste lösningen jag har sett med denna är att bara ha en jävla massa overloads som konverterar objektet man skickar in till en sträng och sen gör tvärtom när man läser ut det. Typ "GetValueBool"

Visa signatur

Asus Striker II Extreme / XFX Geforce GTX 280 / Q9450 @ 3.6GHz/ TRUE Noctua 120/ 4x1GB Corsair TWIN3X2048-1333C9DHX / X25-M G2 80gb Velociraptor / Win 7 Ultimate x64/ Antec P190

MovieDatabase

Permalänk
Medlem

Ta en titt på dynamic keyword som kom i .Net 4.0

Har tyvärr inte möjlighet att testa koden hemma då jag ej har VS 2010 och .NET 4 hemma.
Men tanken är något liknande:

private T Add<T>(T value, T increment) where T : struct { dynamic dynamicValue = (dynamic)value; dynamic dynamicIncrement = (dynamic)increment; dynamic result = dynamicValue + dynamicIncrement; return (T)(object)result; }

Visa signatur

CPU: i7 6700k + Fractal Design S24 GPU: ASUS GeForce GTX 1070 8GB DUAL OC RAM: Kingston 16GB 2133MHz CL13 MB: MSI GAMING M7 PSU: EVGA Supernova G2 850W, 80+ Gold SSD: Samsung SM951 256GB M.2 NVMe + Samsung EVO 850 250GB M.2 Chassi: Fractal Design S Skrämar: Acer XB270HU + 2x Dell U2412M
NAS: Synology DS415+ (4x WD RED 6 TB) Console: Xbox One

Permalänk
Skrivet av Tino:

Ta en titt på dynamic keyword som kom i .Net 4.0

Har tyvärr inte möjlighet att testa koden hemma då jag ej har VS 2010 och .NET 4 hemma.
Men tanken är något liknande:

private T Add<T>(T value, T increment) where T : struct { dynamic dynamicValue = (dynamic)value; dynamic dynamicIncrement = (dynamic)increment; dynamic result = dynamicValue + dynamicIncrement; return (T)(object)result; }

Naturligtvis!

Fungerar perfekt:

private T Testing<T>(string testString, T increment) where T : struct { dynamic dynamicValue = Convert.ChangeType(testString, typeof(T)); return (T)(dynamicValue + (dynamic)increment); }

Tusen tack.

Visa signatur

"Mies saa kaatua mutta ei karata." -- Adolf Ehrnrooth IR 7, Äyräpää 1944.