Laden...

[gelöst] Generischer Typ + is-Operator

Erstellt von typhos vor 17 Jahren Letzter Beitrag vor 17 Jahren 1.628 Views
T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren
[gelöst] Generischer Typ + is-Operator

Hallo,
ich habe mir einen generischen Typ erstellt:

public class Eigenschaft<T>
{
private T _wert;
private string _name;
...

public T Wert
{
get{return _wert;}
set{_wert = value;}
}
...
}

So, jetzt habe ich in einer anderen Klasse diesen Typ benutzt und damit einige Felder definiert:

Eigenschaft<int> intTest = new Eigenschaft<int>();
Eigenschaft<string> stringTest = new Eigenschaft<string>();

An anderer Stelle gehe ich mittels Reflection alle Felder der Klasse durch. Damit erhalte ich natürlich nicht nur die Felder vom Typ Eigenschaft<T>, sondern alle. Ich möchte aber nur die Eigenschaft<T>-Felder. Aus diesem Grund würde ich gern den Typ prüfen:

if (AKTUELLES_FELD is Eigenschaft<T>)

Leider geht das ja nicht so, sondern ich muss für jeden möglichen Typ T einzeln prüfen.

Meine Frage: Gibt es eine Möglichkeit, dieses allgemein abzuprüfen. Also so, wie in der o.g. if-Abfrage? Ich möchte nämlich nur ungern (also eigentlich gar nicht) alle möglichen Typen abdecken. Kommt mal ein neuer dazu, funktioniert es nicht mehr...

Würde mich freuen, wenn jemand eine Möglichkeit dafür kennt! 🙂

3.170 Beiträge seit 2006
vor 17 Jahren

Hallo,
ein interessantes Problem. Vielleoicht klappt es, einfach ein Dummy-Interface ohne Properties oder Methoden zu machen und Deinen generischen Typ davon abzuleiten. Dann kannst Du Deine Typen fragen ob sie vom Typen dieses Interfaces sind, etwa so:

public interface IDummy {}
public class Eigenschaft<T>: IDummy
{
  ...
}
// und für die Abfrage
if (AKTUELLES_FELD is IDummy) 

Allerdings keine Garantie daß es klappt, nur eine Idee.
Außerdem müßtest Du noch aufpassen, daß keine anderen Typen das Interface implementieren, da diese sonst fälschlicherweise auch erkannt würden.

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

1.373 Beiträge seit 2004
vor 17 Jahren

Hallo,

Das ganze geht auch direkt:


// den generischen Typ holen
// statt <string> kann hier auch jeder andere Typ verwendet werden
Type eigenschaftTyp = typeof( Eigenschaft<string> ).GetGenericTypeDefinition();

foreach( PropertyInfo prop in typeof( TestClass ).GetProperties() ) {
    Type propTyp = prop.PropertyType;
    if( propTyp.IsGenericType && 
        propTyp.GetGenericTypeDefinition().Equals(eigenschaftTyp)) {
        // ja, property ist ein Eigenschaft<T>
    }
}

Grüße,
Andre

T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren

Danke auch für diesen Vorschlag. Damit habe ich auch gerade rumgespielt (alos mit GetGenericTypeDefinition). Funktioniert auch!
Allerdings benutze ich jetzt doch die Variante von MarsStein, da der Code dadurch viel übersichtlicher und kürzer ist - auf die Idee mit dem Interface wäre ich nie gekommen, obwohl sie doch sooo nah liegt 😁

Danke nochmal an euch beide! 👍

1.373 Beiträge seit 2004
vor 17 Jahren

Hallo,

Nichts gegen MarsStein, aber du ziehst einen fehleranfälligen Hack einer korrekten Lösung vor? 8o

Grüße,
Andre

T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren

Was ist denn daran fehleranfällig bzw. schlecht? 8o

Wenn das keine gute Lösung ist, dann nehm ich natürlich die von dir genannte Variante. Aber warum ist das denn schlecht?

3.170 Beiträge seit 2006
vor 17 Jahren

Hallo,
die Variante von VizOne ist auf jeden Fall die bessere -> kannte ich aber in der Form auch nicht.
Meine Lösung funktioniert zwar, ist aber auf jeden Fall fehleranfällig, warum steht z.B. in meinem letzten Satz in meinem letzten Beitrag:

Außerdem müßtest Du noch aufpassen, daß keine anderen Typen das Interface implementieren, da diese sonst fälschlicherweise auch erkannt würden.

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren

Ja, das ist mir schon klar, aber das könnte ich ja noch ausschließen. Und ich werde jetzt auch die andere Variante nehmen, aber gibt es denn noch andere Anfälligkeiten für deine Methode?

3.170 Beiträge seit 2006
vor 17 Jahren

Hallo,

sonst fallen mir jetzt eigentlich keine Anfälligkeiten auf, aber Fakt bleibt: Die von mir genannte Lösung ist ein Hack, der Fehler zuläßt, und wenn das Framework eine saubere Lösung bietet, sollte sie auch benutzt werden, schon im Hinblick auf Wartbarkeit und Erweiterbarkeit des Codes... vor allem wenn Du nicht der einzige bist, der den Code benutzt.
Es ist mir nicht ganz klar, wie Du einen wirksamen Schutz gegen die falsche Benutzung von IDummy realisieren willst.

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

121 Beiträge seit 2006
vor 17 Jahren

Hallo beisammen,

Ihr seid alle so schnell beim Antworten - echt Klasse dieses Forum! 👍
In der Zwischenzeit habe ich das mal rausgesucht, es sieht ähnlich aus wie Eure Vorschläge, naja, das hat sich nun überschnitten. Dennoch hier mein Posting:

Gruß Hape


        using System.Collections;
        public static void meinTest()
        {
            // Alternativen zum Probieren:
            //
            Eigenschaft<int> testvar = new Eigenschaft<int>();
            //string testvar = "blabla";
            //List<String> testvar = new List<String>();

            Eigenschaft<string> stringTest = new Eigenschaft<string>();
            if (testvar.GetType().IsGenericType)
                if (typeof(Eigenschaft<>) == testvar.GetType().GetGenericTypeDefinition())
                {
                    Console.WriteLine("*** Es handelt sich um eine Eigenschaft<T>");
                }
                else
                {
                    Console.WriteLine("*** Nein, es ist zwar generic, aber keine Eigenschaft<T>");
                }
            else
            {
                Console.WriteLine("*** Nein, es ist was ganz anderes");
            }
        }

T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren

Hallo,
ich nehme ja jetzt auch die richtige Variante - nochmals Danke dafür.
Mich hat halt nur interessiert, warum deine denn schlecht sein sollte (mal abgesehen von der evtl. anderweitigen Verwendung des Interfaces - das hattest du ja ganz am Anfang schon genannt und daher war mir das schon bewusst).

Aber ist ja auch egal. Ihr habt natürlich Recht, dass die Anfälligkeit für diesen Fehler allein schon völlig reicht, um auf die andere Variante umzusteigen. =)

1.373 Beiträge seit 2004
vor 17 Jahren

Original von hape

  
typeof(Eigenschaft<>)   
  

8o Das kannte ich jetzt aber mal nicht! Danke für den Hinweis! Nur für diejenigen, die das heute auch zum ersten Mal gesehen haben: bei mehreren Typparametern werden einfach Kommata zwischen die spitzen Klammern geschoben, also etwa typeof( Converter<,> ) bei zwei Typparametern, ähnlich wie bei Arrays: int[,] = new .... Danke an hape!

@MarsStein: ich hoffe, du nimmst es mir nicht übel, dass ich deine Lösung als "Hack" bezeichnet habe. Wie du siehst, gibt es immer jemanden, der eine noch bessere Lösung hat 😉

Grüße,
Andre

3.170 Beiträge seit 2006
vor 17 Jahren

@VizOne
ich nehm Dir garnix übel, im Gegenteil: Auch ich freue mich immer wieder, was dazuzulernen. Die wohl Korrekte Bezeichnung "Hack" für meine Lösung habe ich ja dann auch gleich übernommen und für Deine plädiert 😉 wobei ich ja allerdings die sich ergebende Problematik meines "Hacks" auch gleich dazugeschrieben hatte.

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

T
typhos Themenstarter:in
243 Beiträge seit 2006
vor 17 Jahren

Sorry, hape. Ich habe deinen Beitrag leider übersehen!

Danke für deine Lösung mit Eigenschaft<>. Das kannte ich auch noch nicht. Durch diese Lösung konnte ich jetzt noch eine Zeile einsparen ^^