Generische Methode mit dem Parameter Aktion - c #, Generika, Delegaten

Also, ich bin mir sicher, dass das irgendwo schon einmal irgendwo beantwortet wurde, aber ich konnte es nirgends finden. Hoffe, dass einige Generika Guru helfen können.

public interface IAnimal{}
public class Orangutan:IAnimal{}

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
Orangutan orangutan = new Orangutan();
action(orangutan);  //Compile error 1

//This doesn"t work either:
IAnimal animal = new Orangutan();
action(animal);  //Compile error 2
}
  1. Der Argumenttyp "Orang-Utan" ist nicht dem Parametertyp "T" zuweisbar
  2. Argumenttyp "IAnimal" ist nicht dem Parametertyp "T" zuweisbar

Edit: Basierend auf den Vorschlägen von Yuriy und anderenIch könnte einige Castings machen wie:

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
Orangutan orangutan = new Orangutan();
action((T)(IAnimal)orangutan);

//This doesn"t work either:
IAnimal animal = new Orangutan();
action((T)animal);
}

Ich wollte die ValidateUsing-Methode folgendermaßen aufrufen:

ValidateUsing(Foo);

Leider, wenn foo so aussieht:

private void Foo(Orangutan obj)
{
//Do something
}

Ich muss den Typ explizit angeben, wenn ich ValidateUsing aufrufen

ValidateUsing<Orangutan>(Foo);

Antworten:

6 für die Antwort № 1

Warum instanzierst du ein? Orangutan wenn du irgendeinen annehmen sollst IAnimal?

public void ValidateUsing<T>(Action<T> action) where T : IAnimal, new()
{
T animal = new T();
action(animal);  //Compile error 2

Wenn Sie Ihren generischen Parameter wiederverwenden, haben Sie keine Type-Probleme ...

Nun, im Hinblick darauf, warum dein Code nicht funktioniert, ist alles, was du sagst, der Typ T wird von abgeleitet werden IAnimal. Es könnte aber genauso gut sein Giraffe als Orangutan, so können Sie nicht einfach eine zuweisen Orangutan oder IAnimal zu einem Parameter des Typs T.


4 für die Antwort № 2

Die Sache ist, dass T repräsentiert etwas Typ, der übrigens INimal implementiert.

Also, wenn Sie versuchen zu kompilieren action(new Organatum()) Sie erhalten einen Fehler, weil Sie angegeben haben, dass die Aktion einen Parameter vom Typ annehmen soll T was wiederum sein könnte, sagen wir, Fish - Sie können nicht werfen Organatum zu einem Fish, Können Sie?

Wenn Sie eine Aktion auslösen möchten, die Parameter eines Typs enthält, der implementiert IAnimal Schnittstelle, dann einfach über Generika vergessen und verwenden Action<IAnimal>.

HTH.


2 für die Antwort № 3

Nehmen Sie die folgenden Änderungen vor:

Orangutan orangutan = new Orangutan();
action((T)(IAnimal)orangutan);


IAnimal animal = new Orangutan();
action((T)animal);

2 für die Antwort № 4

Versuche dies.

Orangutan orangutan = new Orangutan();
Action<IAnimal> castedAction = action as Action<IAnimal>;
castedAction(orangutan);

0 für die Antwort № 5
public interface IAnimal { }
public class Orangutan : IAnimal { }

public void ValidateUsing<T>(Action<T> action) where T : IAnimal
{
Orangutan orangutan = new Orangutan();
action((T)(orangutan as IAnimal));  // needs to be cast as IAnimal

//This doesn"t work either:
IAnimal animal = new Orangutan();
action((T)animal);  // needs to be cast as T
}

Es scheint auch, dass die Tatsache, dass es eine Schnittstelle ist, einen Unterschied macht. Wenn Sie eine abstrakte Klasse Animal anstelle einer Schnittstelle hätten, könnten Sie das tun:

public abstract class Animal { }
public class Orangutan : Animal { }

public void ValidateUsing<T>(Action<T> action) where T : Animal
{
Orangutan orangutan = new Orangutan();
action(orangutan as T);

//This doesn"t work either:
Animal animal = new Orangutan();
action(animal as T);
}

Speisekarte