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

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

1

13.09.2015, 23:29

[C#] Casts mit Templates funktionieren nicht

Hallo Leute,

ich habe folgende Klassensignaturen:

C#-Quelltext

1
2
3
4
5
public class EffectRGBParameterSlot : EffectParameterSlot<EffectRGBParameter>
{
    // Hier steht kein erweiternder Code - nur ein paar mit der Basisklasse identische Konstruktoren
}
public abstract class EffectRGBParameter : EffectParameter<Color> { }

Und die folgende (sinnlose) Methodensignatur:

C#-Quelltext

1
public DoStaff(EffectParameterSlot<EffectParameter<Color>> Something);
Diese Methode gehört einer Templateklasse an, darum kann ich nicht einfach EffectRGBParameterSlot in der Signatur schreiben. :(

Nun folgender Code:

C#-Quelltext

1
2
EffectRGBParameterSlot Slot = new EffectRGBParameterSlot();
DoStaff(Slot);

Warum kann ich sowas nicht machen bzw. warum sagt mir der VSC 2015 Compiler, dass er EffectRGBParameterSlot nicht in EffectParameterSlot<EffectParameter<Color>> casten kann!? Die beiden Typen sind doch identisch, wenn ich die Templates ineinander einsetze? Oder frisst der Compiler das nicht, weil es keine C++ Typedefs, sondern "neue" Klassen sind!?

Damit keiner fragt, warum ich sowas mache: Die Templates brauche ich zwingend, weil ich sonst wild werde, wenn ich die gleichen Funktionen für 10 verschiedene Typen programmieren muss... Die Klassendefinitionen, wo aus einer Template-Klasse eine Klasse gemacht wird, brauche ich, weil ich in WPF Datatemplates für die verschiedenen Typen coden möchte und XAML ja keine Templates als Datatype akzeptiert...

Ich hoffe, das war einigermaßen verständlich - und es gibt eine Lösung! Vielleicht auch einfach für das WPF-Template-Problem... Also dass ich einem DataTemplate eine Templateklasse (mit ausgefüllten Templateparametern) als DataType übergeben kann.
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

Tobiking

1x Rätselkönig

  • Private Nachricht senden

2

14.09.2015, 00:44

Du hast da eine Vererbungshierarchie in den Typparametern und mit dem Funktionsaufruf von DoStaff castest du implizit Generic<Derived> nach Generic<Base>. Wenn Generic Funktionen enthält die Parameter vom Typ des Typparameters haben, bekommen die Instanzen vom Typ Base statt Derived. So rum funktioniert Polymorphie nicht.

In C# kann man bei Interfaces begrenzen ob der Typparameter für Returnwerte oder Parameter verwendet wird und damit Ko- und Kontravarianz erzielen, womit diese Richtung durchaus ginge (https://msdn.microsoft.com/de-de/library/Dd997386.aspx). Allerdings glaube ich nicht das es dein Problem löst. Es reicht aber das EffectRGBParameterSlot direkt von EffectParameterSlot<EffectParameter<Color>> erbt damit es in XAML verwendbar ist.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

3

14.09.2015, 00:52

Erstens: Es gibt keine Templates in C#. C# hat nur Generics; die sind zwar für mehr oder weniger den selben Zweck gedacht, funktionieren aber völlig anders als Templates in C++.

Gut, nachdem wir das mal klargestellt haben, nun zum Rest... ;)

Warum kann ich sowas nicht machen bzw. warum sagt mir der VSC 2015 Compiler, dass er EffectRGBParameterSlot nicht in EffectParameterSlot<EffectParameter<Color>> casten kann!? Die beiden Typen sind doch identisch, wenn ich die Templates ineinander einsetze? Oder frisst der Compiler das nicht, weil es keine C++ Typedefs, sondern "neue" Klassen sind!?

Nein, die beiden Typen sind nicht identisch. EffectRGBParameterSlot ist ein eigener Typ. Die Ableitung drückt lediglich aus, dass jeder EffectRGBParameterSlot auch ein EffectParameterSlot<EffectRGBParameter> ist aber nicht umgekehrt. Genauso ist EffectRGBParameter ein eigener Typ. Die Ableitung drückt lediglich aus, dass jeder EffectRGBParameter auch ein EffectParameter<Color> ist aber nicht umgekehrt. Da nicht unbedingt jeder EffectParameter<Color> ein EffectRGBParameter ist (ich kann ja überall wo ich will einfach eine neue Klasse von EffectParameter<Color> ableiten), kann erst recht nicht gelten, dass jeder EffectParameterSlot<EffectParameter<Color>> ein EffectParameterSlot<EffectRGBParameter> ist...

https://msdn.microsoft.com/library/ee956431.aspx
https://msdn.microsoft.com/en-us/library/aa664765.aspx

Have Fun ;)

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »dot« (14.09.2015, 01:04)


CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

4

14.09.2015, 18:59

Danke schonmal für eure informativen Antworten! :) Ich habe ein paar Fragen:

Es reicht aber das EffectRGBParameterSlot direkt von EffectParameterSlot<EffectParameter<Color>> erbt damit es in XAML verwendbar ist.
Ich definiere also ein DataTemplate mit dem DataType EffectRGBParameterSlot und wenn dann ein EffectParameterSlot<EffectParameter<Color>> angezeigt werden soll, dann wird das DataTemplate benutzt!? Das glaube ich nicht, das wäre doch ein Up-Cast, der nicht möglich ist.

Es gibt keine Templates in C#. C# hat nur Generics;
Danke für die Info - jetzt weiß ich, warum ich bei der Eingabe von "C# Templates" nicht so super Sachen finde... Bei "C# Generics" sieht das schon viel besser aus! ;)

Nein, die beiden Typen sind nicht identisch. EffectRGBParameterSlot ist ein eigener Typ.
OK, das hatte ich befürchtet! Es ist also kein C++-artiger typedef, sondern eine neue Klasse. Die "Using-Aliasen" habe ich eben ausprobiert - funktioniert ja ganz gut! Gibts ne Möglichkeit sowas zu machen:

C#-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// Datei: EffectParameter.cs

namespace ACALC
{
    using EffectRGBParameter = EffectParameter<Color>;
    public abstract class EffectParameter<T>
    {
        // Code
    }
}

// Datei: EffectParameterSlot.cs
namespace ACALC
{
    public class SomeClass
    {
        public void DoStaff(EffectRGBParameter p)
        {
            // Code
        }
    }
}
Da bekomme ich in der zweiten Datei eine Meldung, dass er EffectRGBParameter nicht kennt. Kann ich den Alias dateiübergreifend definieren?

In Dots erstem Link steht, dass ich Objekte aus einer Generic-Class erstellen kann. So eine Angabe funktioniert aber nicht bei der DataType-Eigenschaft der DataTemplates. :( Laut INET ist dort die Angabe eines generischen Typs ohne "Tricks" auch nicht möglich. Ich bin jetzt nicht so scharf drauf, mit so Tricks (Markupextension oder einfach dran zu Binden und hoffen dass es klappt) zu spielen...

Ist ein DataTemplateSelector eine schöne Möglichkeit, das mit den WPF-"Bordmitteln" zu lösen? Die (10) möglichen Typen, die für die Generics möglich sind, kenne ich ja...
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

5

15.09.2015, 08:55

Nein, die beiden Typen sind nicht identisch. EffectRGBParameterSlot ist ein eigener Typ.
OK, das hatte ich befürchtet! Es ist also kein C++-artiger typedef, sondern eine neue Klasse.

Ich kann ehrlich gesagt nicht nachvollziehen, wie genau du überhaupt erst auf die Idee kommst, dass eine abgeleitete Klasse in C# sowas wie ein typedef sein könnte, das macht erstens und zweitens keinen Sinn und ist drittens doch auch in C++ schon nicht so!?

Die "Using-Aliasen" habe ich eben ausprobiert - funktioniert ja ganz gut! Gibts ne Möglichkeit sowas zu machen [...] Da bekomme ich in der zweiten Datei eine Meldung, dass er EffectRGBParameter nicht kennt. Kann ich den Alias dateiübergreifend definieren?

Using Aliase sind wohl bei weitem das Näheste an C++ typedefs, an das du in C# herankommen wirst (using alias declarations gibt's übrigens auch in C++ und dort sind die sowas wie typedefs ;)). Afaik gibt's leider keinen Weg, die in C# "Dateiübergreifend" zu machen.

Ich bin kein WPF Experte, aber ich möchte einfach mal anmerken, dass WPF eine ganz normale .NET Library ist, die man auch direkt in C# ansprechen kann. XAML ist praktisch, aber alles was man in XAML hinschreiben kann, kann man auch direkt in C# hinschreiben...

6

15.09.2015, 15:43

Bei der Verwendung des CRTP muss man in C# manchmal mit generic type constraints arbeiten. Also bei generischen Methoden oder Klassen ein where T: EffectParameterSlot<T> anhängen. Dann sollte auch ein cast klappen.

CeDoMain

Alter Hase

  • »CeDoMain« ist der Autor dieses Themas

Beiträge: 587

Wohnort: Ilmenau

Beruf: Student für Mechatronik

  • Private Nachricht senden

7

15.09.2015, 17:44

Ich kann ehrlich gesagt nicht nachvollziehen, wie genau du überhaupt erst auf die Idee kommst, dass eine abgeleitete Klasse in C# sowas wie ein typedef sein könnte, das macht erstens und zweitens keinen Sinn und ist drittens doch auch in C++ schon nicht so!?
Ich habe hier gelesen, dass ich ein Generic mithilfe einer neuen Klasse als DataType an ein DataTemplate übergeben kann. Eine weitere Seite (kann leider nicht wiederfinden :( ) hat das ganze auch als C++-artigen typedef bezeichnet. Dass das eigentlich nicht das gleiche sein kann, habe ich mir schon gedacht, nur ist der C# Compiler vielleicht so schlau zu merken, dass die neue Klasse genauso wie die Basisklasse ist und das dann als typedef zu interpretieren... (ja, das ist ein wenig naiv) Dass das in C++ so ist, weiß ich - mit C++ kenne ich mich auf dem Gebiet besser aus! :)

Afaik gibt's leider keinen Weg, die in C# "Dateiübergreifend" zu machen.
OK - danke für diese Aussage - meine Fragen sind jetzt erstmal geklärt denke ich! Dankeschön. :)

Ich bin kein WPF Experte, aber ich möchte einfach mal anmerken, dass WPF eine ganz normale .NET Library ist, die man auch direkt in C# ansprechen kann. XAML ist praktisch, aber alles was man in XAML hinschreiben kann, kann man auch direkt in C# hinschreiben...
Das mache ich jetzt auch mit einem TemplateSelector!

Verwendung des CRTP
Sowas verwende ich doch garnicht!? Ansonsten: where T: kenne ich - immerhin etwas. ;)
Mit freundlichem Gruß
CeDo
Discord: #6996 | Skype: cedomain

Lass solche persönlichen Angriffe lieber bleiben, meine sind härter.

8

15.09.2015, 19:38

Sowas verwende ich doch garnicht!?


Oops, ja sieht nicht so aus. Tut mir leid für die Verwirrung. Trotzdem: Type constraints könnten weiterhelfen.

Werbeanzeige