C# Allgemeine Generic Frage

Rooky420

Cadet 4th Year
Registriert
Nov. 2015
Beiträge
98
Hallo,

ich habe ein verständnissproblem mit Generics in C#.
Ich habe folgenden Code:
Code:
namespace Test
{
    class Test
    {
        public static void DoSth<T>()
        {
            //Do Work
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Type integer = typeof(Int32);
            Test.DoSth<integer>(); //integer wirft Fehler: The type or namespace name 'integer' could not be found
            Test.DoSth<Int32>(); //funktioniert
        }
    }
}

So wie ich das verstanden habe verwendet man ja Generics um Typabhänig in klassen und methoden zu arbeiten.
Warum kann man dann nicht ein objekt der klasse Type übergeben?
Ist es irgendwie möglich ein typeobjekt einer generischen methode oder klasse zu übergeben?

Grüße,
Rooky420
 
Hi,

Generics sind nicht dazu da, Datentypen (was int in C# ist) anzugeben, sondern Klassen.

Int32 macht da eine Ausnahme, weil es sich um ein Struct handelt glaub ich.

Hoffe das bringt dich auf einen Lösungsweg.

Mfg

Saphirim
 
Int32 ist die Wrapperklasse von int
Test.DoSth<typeof(Test)>(); würde auch nicht funktionieren.
 
Int32 ist nicht nur eine simple Wrapperklasse, sondern tatsächlich ein struct und ist definiert als:
Code:
[SerializableAttribute]
[ComVisibleAttribute(true)]
public struct Int32 : IComparable, IFormattable, IConvertible, 
	IComparable<int>, IEquatable<int>

Außerdem: Du verwendest typeof, welches zur compile Zeit aufgelöst. GetType wird zur Laufzeit aufgelöst. Großer Unterschied wenn du mit Vererbung arbeitest

Beispiel:
Code:
class Cat : Animal
{
   //Cat specific meows
}

static void Main()
{
   Animal c = new Cat();
   c.GetType(); // returns typeof(Cat)
}


Aber wieso willst du diese Zeile mit
Code:
Type integer = typeof(Int32);
überhaupt verwenden?
 
Jesterfox schrieb:
Du übergibst bei den Generics kein Objekt der Typklasse sondern direkt eine Klasse.

Das weiß ich aber ich will wissen:
Warum kann man dann nicht ein objekt der klasse Type übergeben? "Warum? gibt es einen grund für das verhalten?"
Ist es irgendwie möglich ein typeobjekt einer generischen methode oder klasse zu übergeben? "Möglichkeiten um ein dynamisches objekt der klasse Type übergeben zu können"
 
Gnannondorf schrieb:
Int32 ist nicht nur eine simple Wrapperklasse, sondern tatsächlich ein struct und ist definiert als:
Code:
[SerializableAttribute]
[ComVisibleAttribute(true)]
public struct Int32 : IComparable, IFormattable, IConvertible, 
	IComparable<int>, IEquatable<int>

Außerdem: Du verwendest typeof, welches zur compile Zeit aufgelöst. GetType wird zur Laufzeit aufgelöst. Großer Unterschied wenn du mit Vererbung arbeitest

Beispiel:
Code:
class Cat : Animal
{
   //Cat specific meows
}

static void Main()
{
   Animal c = new Cat();
   c.GetType(); // returns typeof(Cat)
}


Aber wieso willst du diese Zeile mit
Code:
Type integer = typeof(Int32);
überhaupt verwenden?

Danke für die Antwort.
Meiner Meinung nach müsste es ja funktionieren da das Objekt von Type die Informationen einer klasse speichern kann.

Verwenden könnte man dies z.b. Um ein Interface wieder in seine urspüngliche klasse zu casten oder andere vereinfachen dinge...
 
Vielleicht hilft dir das weiter:

Code:
MethodInfo method = typeof(Test).GetMethod("DoSth");
MethodInfo generic = method.MakeGenericMethod(myType);
generic.Invoke(this, null);

Das funktioniert solange, wie die generische Methode public ist. Ansonsten musst du GetMethod mit BindingFlags.NonPublic | BindingFlags.Instance aufrufen, also:

Code:
MethodInfo method = typeof(Test).GetMethod("DoSth", BindingFlags.NonPublic | BindingFlags.Instance);
 
Rooky420 schrieb:
Warum kann man dann nicht ein objekt der klasse Type übergeben? "Warum? gibt es einen grund für das verhalten?"

Weil Generics ein Compiler-Konstrukt sind die Typsicherheit liefern sollen. Genauso wenig kannst du ja bei einer Variablendefinition ein Typeobject statt einer Klasse für den Typ nehmen. Das würde die gewollte Typsicherheit unterwandern.

Die Frage ist was du eigentlich vor hast... wenn es nur darum geht in der Methode das Typeobject zu nutzen kannst du es dir mittels typeof(T) holen. Überprüfen ob das übergebene Objekt einer bestimmten Klassen angehört und es darauf casten ist auch ganz normal möglich.
 
@Rooky
Der Typ einer generischen Methode muss zur Compilezeit bekannt sein, deswegen kannst du nicht einfach eine Variable als Typparameter angeben, da diese nach dem kompilieren (während der Laufzeit) veränderbar ist.

Was hindert dich denn daran innerhalb einer generischen Methode ein Interface in einen anderen Typ zu casten?
Code:
void Foo<T>(T arg)
{
    if(arg is Bar)
    {
        var bar = (Bar)arg;
    }
}

Klar könntest du per Reflection zur Laufzeit an bestehenden Methoden rumpfuschen oder neue generieren, aber du machst dir damit auch die Typsicherheit kaputt.
 
Grantig schrieb:
@Rooky
Der Typ einer generischen Methode muss zur Compilezeit bekannt sein, deswegen kannst du nicht einfach eine Variable als Typparameter angeben, da diese nach dem kompilieren (während der Laufzeit) veränderbar ist.
Hallo,
na so ganz stimmt das ja nicht. Im Gegensatz zu C++ Templates können Generics polymorph sein. Daher sind diese eben nicht Kompilier- sondern Laufzeit gebunden.

greetz
​hroessler
 
Ja, .NET Generics sind Laufzeitgebunden, dem habe ich nie widersprochen ;)

MSDN schrieb:
Generics shift the burden of type safety from you to the compiler. There is no need to write code to test for the correct data type because it is enforced at compile time.
Quelle: Generics in the .NET Framework

Der C# Compiler erzwingt Typsicherheit schon beim kompilieren in CIL, weil auch die (statische) overload resolution zur Compilezeit stattfindet, was ohne konkrete Typinformationen nicht möglich wäre.
 
Was du willst geht bereits.
Du kannst ein objekt von der Klasse Type als Argument übergeben.
Dazu brauchst du keine Generische Methode.

Hört sich sehr nach einem XY-Problem an.

Ansonsten vielleicht hilft dir noch der hinweis dass der Typ eines Arguments bei einer generisches Methode implizit erkannt wird.

E.g.
Code:
        public static void TestGeneric<T>(T obj)
        {

        }

        public static void Call()
        {
            int a = 4;
            TestGeneric(a);
        }

So wie ich das verstanden habe verwendet man ja Generics um Typabhänig in klassen und methoden zu arbeiten.

Jein.
Bestes beispiel für eine generische Klasse ist List<T>.

Durch den Generic T hast du typsicherheit bei allen Operationen mit der List.
Alle Add, AddRange etc. Methoden sind Add<T>,AddRange<T>(IEnumerable<T>) wodurch forciert wird dass du immer den gleichen Typen hast.

Bei einer Methode mit einfach nur einem Input und ohne rückgabe macht es kaum Sinn diese Generisch zu machen.
Da kannst du genau so gut den BasisTypen/Interface als argument verwenden.

Du kannst bei einzelnen Methoden Generics verwenden um z.b. den gleichen Typen für 2 Argumente zu erzwingen, oder deinen Rückgabewert abhängig vom Input zu machen:

Code:
public T ReturnRandom<T>(T a, T b)
{
return a; //decided by diceroll
}

Von außen hast du hier eine Typsichere methode.
Der Kompiler sorgt dafür dass wenn a ein int ist sowohl b als auch der Rückgabewert ein int sind.
 
Zurück
Oben