Laden...

[gelöst] Fehlende Referenz für Überladene Methode die jedoch nicht aufgerufen wird (CompileError)

Erstellt von rollerfreak2 vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.583 Views
rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 12 Jahren
[gelöst] Fehlende Referenz für Überladene Methode die jedoch nicht aufgerufen wird (CompileError)

Hi zusammen,

ich habe ein kleines Problem und versteh das Verhalten des .NET Compilers nicht ganz. Folgendes Szenario:


//AssemblyB
public interface InterfaceB
{
    int Add(double a, double b);
}


//AssemblyA
public interface InterfaceA
{
    int Add(int a, int b);

    int Add(InterfaceB b1, InterfaceB b2);
}


//AssemblyC
static void Main(string[] args)
{
    object a = new object();
    InterfaceA b = (InterfaceA)a;
    b.Add((int)1, (int)2);
}

Der Code in Main macht zwar so keinen Sinn ich wollte nur das Problem darstellen. In AssemblyC habe ich natürlich nur eine Referenz auf die AssemblyA weil ich ja das Interface dort adressiere. Das Problem nur ist das eine Überladung der Methode existiert in der ein Interface aus AssemblyB verwendet wird. Das führt dazu das ich einen Compilerfehler bekomme. > Fehlermeldung:

The Type InterfaceB is defined in an assembly that is not referenced. You must add a reference to assembly AssemblyB. Ich muss eine Referenz auf AssemblyB hinzufügen damit der Code compiliert obwohl ich keinen Typen dieses Assemblies direkt referenziere! Wieso erkennt der Compiler nicht die genaue Überladung bzw. wieso braucht er eine Referenz auf eine Überladung die ich im Code doch gar nicht referenziere?

Gibt es eventuell eine Lösung den Compiler zu übereden ohne eine Referenz auf AssemblyB hinzuzufügen und auch ohne die Signaturen zu ändern?

Again what learned...

6.862 Beiträge seit 2003
vor 12 Jahren

Hallo,

Assembly A wird von C geladen, sonst könntest du es ja nicht nutzen. Und A hat als Referenz B. Daher brauch C auch B über A. Da kannst du nichts ändern. Was für Methoden du im konkreten aufrufst ist egal, die Assemblies müssen immer komplett geladen werden.

Baka wa shinanakya naoranai.

Mein XING Profil.

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 12 Jahren

Nein das ist falsch so wie du das sagst. Wenn ich im AssemblyA die Signature so ändere das es keine Überladung ist daher in


//AssemblyA
public interface InterfaceA
{
    int Add(int a, int b);

    int Add1(InterfaceB b1, InterfaceB b2);
} 

dann brauch ich in AssemblyC natürlich auch nur eine Referenz auf das AssemblyB weil ich in Main auf InterfaceB gar nicht zugreife. Bei der Überladung will der Compiler allerdings die Referenz haben obwohl ich die Signature mit InterfaceB nicht aufrufe!

Again what learned...

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 12 Jahren

Ich habe eine Lösung gefunden wie man den Compiler überlisten kann. Das Zauberwort heißt Names Parameters.

Wenn man die Methode in der Main so called dann wird der Compiler gezwungen die Methode anhand der Parameter-Namen zu identifizieren. Die Referenz auf das AssemblyB ist dann nicht mehr nötig!


//AssemblyC
static void Main(string[] args)
{
    object a = new object();
    InterfaceA b = (InterfaceA)a;
    b.Add(a : 1, b : 2);
} 

Ein guter Artikel dazu ist Named Parameters.

Again what learned...

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo rollerfreak2,

der Typ aus Assembly B taucht in der öffentlichen Schnittstelle der Assembly A auf. Selbst wenn du diesen Typen in Assembly C nicht benutzt, solltest du nach meinen Verständnis in C eine Referenz auf B hinzufügen.

Zum einen, weil es leicht passieren kann, dass eine vorher unbenutzte Methode später doch benutzt wird.

Zum anderen, weil es nicht nur statische, sondern auch dynamische Zugriffe geben kann (Reflection), und dann würde es zur Laufzeit knallen.

Oder du änderst den Code so, dass AssemblyC in sich abgeschlossen komplett ist, also alle Typen definiert, die als Parameter auftauchen.

herbivore

rollerfreak2 Themenstarter:in
916 Beiträge seit 2008
vor 12 Jahren

Hallo herbivore,

Selbst wenn du diesen Typen in Assembly C nicht benutzt, solltest du nach meinen Verständnis in C eine Referenz auf B hinzufügen.

Das sehe ich nicht so. Zur Laufzeit ist die AssemblyC im selben Ordner wie AssemblyA. Es ist ein sehr großes Projekt wo mehrere Assemblies nebeneinander liegen das heißt zur Laufzeit knallt es m.M.n. nicht auch wenn man mit Reflection dort ein Typ laden will.

Zum einen, weil es leicht passieren kann, dass eine vorher unbenutzte Methode später doch benutzt wird.

Wenn dieser Fall auftritt, dann muss der Entwickler sowieso die Referenz hinzufügen weil er sonst einen Compiler-Fehler bekommt. Ich sehe das nicht als Nachteil!

Again what learned...