[C#] Generisk typ till <type> ?

Permalänk

[C#] Generisk typ till <type> ?

God kväll.

Jag går rakt på sak, ta en titt på följande kod:

static void Main(string[] args) { Dictionary<string, string> dStr = new Dictionary<string,string>(); dStr["Hello"] = "World"; SomeGenericFunc<string>(dStr); Dictionary<string, int> dInt = new Dictionary<string, int>(); dInt["Age"] = 10; SomeGenericFunc<int>(dInt); Console.Read(); } private static void SomeGenericFunc<T>(Dictionary<string, T> dict) { foreach (KeyValuePair<string, T> pair in dict) { // Funkar ju men inte tillräckligt generiskt... T t = pair.Value; if (typeof(T) == typeof(string)) { SomeFunc((string)(object)t); } else if (typeof(T) == typeof(int)) { SomeFunc((int)(object)t); } // Vill kunna anropa rätt överlagrad metod direkt: SomeFunc(t); // Fungerar ej.. } } private static void SomeFunc(int nVal) { Console.WriteLine(nVal); } private static void SomeFunc(string strVal) { Console.WriteLine(strVal); }

Som ni ser vill jag inte behöva kolla vilken typ 't' är av för att anropa rätt överlagrad metod utan vill konvertera 't' till sin "riktiga" typ och anropa rätt direkt.
Jag har börjat läsa i TypeConverter-djungeln men ej hittat nåt än.

Tackar för mig.

Visa signatur

Min dator är bättre än din.

Permalänk
Medlem

Om du bara vill göra det som du visar så kan du ju köra att du tar in ett object. och kör object.toString();

dock om du vill göra mer avanserade sakerså kan du väll göra someFunction generic också ? och lägga den i din Dictionary class? alternatvit lägga detta i en ny klass som ärver från Dictionary

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
Medlem

Hmm, antar att det beror lite på vad du ska använda det hela till. Men som ett förslag så kommer jag med följande lösning:

static void Main(string[] args) { Dictionary<string, IYourOddObject> dStr = new Dictionary<string,IYourOddObject>(); dStr["Hello"] = new OddStringObject("World"); SomeGenericFunc<string>(dStr); Dictionary<string, int> dInt = new Dictionary<string, int>(); dInt["Age"] = new OddIntObject(10); SomeGenericFunc<int>(dInt); Console.Read(); } private static void SomeGenericFunc<T>(Dictionary<string, T> dict) where T : IYourOddObject { foreach (KeyValuePair<string, T> pair in dict) { pair.Value.SomeFunc(); } }

Där dina skapade klasser ärver av ett interface som har funktionen SomeFunc. Ger en bättre struktur och öppnar möjligheter enligt lilla mig. Lycka till med vad du än försöker göra

Permalänk

Tack för era svar, och för att förtydliga mitt problem så postar jag motsvarande kod i C++, precis så som jag vill att det hela ska fungera:

#include <map> #include <iostream> #include <string> void SomeFunc( int nVal ) { std::cout << nVal << std::endl; } void SomeFunc( std::string strVal ) { std::cout << strVal << std::endl; } template <typename T> void SomeGenericFunc( std::map<std::string, T> theMap ) { std::map<std::string, T>::const_iterator it; for( it = theMap.begin(); it != theMap.end(); it++ ) { SomeFunc( it->second ); } } int main( void ) { typedef std::map<std::string, std::string> strMap; typedef std::pair<std::string, std::string> strPair; typedef std::map<std::string, int> intMap; typedef std::pair<std::string, int> intPair; strMap map1; intMap map2; map1.insert( strPair("Hello", "World") ); SomeGenericFunc<std::string>( map1 ); map2.insert( intPair( "Hello", 10 ) ); SomeGenericFunc<int>( map2 ); std::cin >> std::ws; return 0; }

Detta fungerar utmärkt i C++ och jag vill ha precis samma effekt i C# - Hur?

Peo_Bond; mycket trevligt förslag men haken är att jag inte kan (får) ändra på de Dictionary<>-typerna som finns, inte heller på SomeFunc()-metoderna. Glömde tala om det i första inlägget.

/John

Visa signatur

Min dator är bättre än din.

Permalänk
Medlem
Citat:

Ursprungligen inskrivet av Tungviktarn
Tack för era svar, och för att förtydliga mitt problem så postar jag motsvarande kod i C++, precis så som jag vill att det hela ska fungera:

#include <map> #include <iostream> #include <string> void SomeFunc( int nVal ) { std::cout << nVal << std::endl; } void SomeFunc( std::string strVal ) { std::cout << strVal << std::endl; } template <typename T> void SomeGenericFunc( std::map<std::string, T> theMap ) { std::map<std::string, T>::const_iterator it; for( it = theMap.begin(); it != theMap.end(); it++ ) { SomeFunc( it->second ); } } int main( void ) { typedef std::map<std::string, std::string> strMap; typedef std::pair<std::string, std::string> strPair; typedef std::map<std::string, int> intMap; typedef std::pair<std::string, int> intPair; strMap map1; intMap map2; map1.insert( strPair("Hello", "World") ); SomeGenericFunc<std::string>( map1 ); map2.insert( intPair( "Hello", 10 ) ); SomeGenericFunc<int>( map2 ); std::cin >> std::ws; return 0; }

Detta fungerar utmärkt i C++ och jag vill ha precis samma effekt i C# - Hur?

Peo_Bond; mycket trevligt förslag men haken är att jag inte kan (får) ändra på de Dictionary<>-typerna som finns, inte heller på SomeFunc()-metoderna. Glömde tala om det i första inlägget.

/John

Detta finns i Java också och det är ett krav att använda det efter 1.6. Jag tror inte detta går att göra i C#. Jag har googlat som en tok men hittar inte på någon som bekräftar att det fungerar. Jag löste det genom att lagra "object":s istället och sen convertera om dem bäst jag vill sen.

Skulle gärna vilja ha detta i C#.

Visa signatur

ηλί, ηλί, λαμά σαβαχθανί!?

Permalänk
Medlem
Citat:

C++ allows code that might not be valid for all type parameters in the template, which is then checked for the specific type used as the type parameter. C# requires code in a class to be written in such a way that it will work with any type that satisfies the constraints. For example, in C++ it is possible to write a function that uses the arithmetic operators + and - on objects of the type parameter, which will produce an error at the time of instantiation of the template with a type that does not support these operators. C# disallows this; the only language constructs allowed are those that can be deduced from the constraints.

Källa: http://msdn.microsoft.com/en-us/library/c6cyy67b(VS.80).aspx

Det jag kan tänka mig med dina begränsningar är väl då att använda dig av is och as för att snygga till kastandet lite

if (t is string) { SomeFunc(t as string); } else if (t is int) { //Fungerar inte för int då den blir null om ett fel uppstår SomeFunc((int)(object)t); }

Men det är ju en ren smaksak

Permalänk

Bättre sent än aldrig

För den intresserade:

class Program { static void Main(string[] args) { Dictionary<string, string> dStr = new Dictionary<string,string>(); dStr["Hello"] = "World"; SomeGenericFunc<string>(dStr); Dictionary<string, int> dInt = new Dictionary<string, int>(); dInt["Age"] = 10; SomeGenericFunc<int>(dInt); Console.Read(); } public static void SomeGenericFunc<T>(Dictionary<string, T> dict) { foreach (KeyValuePair<string, T> pair in dict) { MethodInfo mInfo = typeof(Program).GetMethod("SomeFunc", new Type[] { typeof(T) }); mInfo.Invoke(null, new object[] { pair.Value }); } } public static void SomeFunc(int nVal) { Console.WriteLine(nVal); } public static void SomeFunc(string strVal) { Console.WriteLine(strVal); } }

Visa signatur

Min dator är bättre än din.

Permalänk

De va la sent det Bättre sent än aldrig som sagt

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