8

Quindi ho letto Eric Lippert's 'Constraints are not part of the signature' e ora capisco che le specifiche specificano che i vincoli di tipo vengono controllati DOPO la risoluzione di sovraccarico, ma non sono ancora chiaro sul perché questo DEVE essere il caso. Di seguito è riportato l'esempio di Eric:Perché la restrizione del tipo non è parte della firma del metodo?

Questo non viene compilato perché la risoluzione di sovraccarico per: Foo(new Giraffe()) ne deduce che Foo<Giraffe> è la miglior partita di sovraccarico, ma poi i vincoli di tipo falliscono e un errore di compilazione viene generata. Nelle parole di Eric:

Il principio è la risoluzione di sovraccarico (e il tipo di metodo di deduzione) trovare la migliore corrispondenza possibile tra un elenco di argomenti e la lista di ogni metodo candidato di parametri formali. Cioè, guardano la firma del metodo candidato.

I vincoli di tipo NON fanno parte della firma, ma perché non possono essere? Quali sono alcuni scenari in cui è una cattiva idea considerare i vincoli di tipo parte della firma? È solo difficile o impossibile da implementare? Non sto sostenendo che se il sovraccarico scelto migliore è per qualsiasi motivo impossibile da chiamare, allora silenziosamente ripiego al secondo migliore; Lo odierò. Sto solo cercando di capire perché i vincoli di tipo non possono essere utilizzati per influenzare la scelta del sovraccarico migliore.

sto immaginando che internamente al compilatore C#, solo per scopi di risoluzione di sovraccarico (non riscrivere in modo permanente il metodo), il seguente:

static void Foo<T>(T t) where T : Reptile { } 

si trasforma a:

static void Foo(Reptile t) { } 

Perché non è possibile "inserire" i vincoli di tipo nell'elenco dei parametri formali? In che modo questo cambia la firma in modo negativo? Sento che rafforza solo la firma. Quindi Foo<Reptile> non sarà mai considerato un candidato sovraccarico.

Modifica 2: Nessuna meraviglia che la mia domanda fosse così confusa. Non ho letto correttamente il blog di Eric e ho citato l'esempio sbagliato. Ho modificato nell'esempio che ritengo più appropriato. Ho anche cambiato il titolo per essere più specifico. Questa domanda non sembra semplice come ho immaginato, forse mi manca qualche concetto importante. Sono meno sicuro che si tratti di materiale stackoverflow, potrebbe essere meglio spostare questa domanda/discussione altrove.

+1

Il bit sulle iguane che hai citato nella parte superiore della tua domanda aveva lo scopo di illustrare una situazione in cui l'inferenza di tipo * fa * un vincolo in considerazione, vale a dire, il vincolo su T in C , e quindi la risoluzione di sovraccarico in ultima analisi sceglie il metodo * non generico * in questo esempio. Sei * sicuro * che è il pezzo rilevante dell'articolo che intendi citare per porre questa domanda? Il resto della domanda non sembra seguire logicamente da esso. –

+1

Penso piuttosto che volevi chiedere perché è quando l'inferenza di tipo * ha esito positivo * ma deduce un tipo che viola un vincolo * sul parametro tipo di metodo *, perché la risoluzione di sovraccarico non riesce quando c'è un'alternativa. Sto trovando questa domanda molto confusa, ma poi di nuovo, è una parte confusa delle specifiche. –

+0

Hai ragione. Ho letto male il tuo blog e ho usato l'esempio sbagliato. Nessuna meraviglia che la mia domanda fosse così confusa. Ho cercato di chiarire la mia domanda nel miglior modo possibile; Inoltre leggerò alcuni dei tuoi altri post sul blog per vedere se riesco a migliorare la mia comprensione sull'argomento. – Daryl

risposta

4

il compilatore C# deve non considerare vincoli di tipo come parte come la firma del metodo, perché non fanno parte della firma del metodo per il CLR. Sarebbe disastroso se la risoluzione di sovraccarico funzionasse in modo diverso per linguaggi diversi (principalmente a causa del legame dinamico che potrebbe verificarsi in fase di esecuzione e non dovrebbe essere diverso da una lingua all'altra, altrimenti tutti gli inferni si scatenerebbero).

Perché è stato deciso che questi vincoli non avrebbero fatto parte della firma del metodo per il CLR è un'altra domanda a parte, e ho potuto fare solo supposizioni informate su questo. Farò sapere alle persone che lo sanno.

+0

Ma questo sposta semplicemente la domanda da "perché non fa parte di C#, perché non fa parte del CLR" ... C'è un problema principale con il supporto della risoluzione di sovraccarico che considera i vincoli di tipo (vedi la mia risposta) . –

+0

Ci sono diverse funzionalità in diversi linguaggi .Net che non sono implementati dagli altri. Il motivo per lo più dato è che una sintassi ausiliaria può essere banalmente convertita in sintassi corretta. Questo è uno dei più semplici, semplicemente per determinare quale metodo chiamare per posizionare. Inoltre, questo non sarebbe l'unico caso di possibile ambiguità nella lingua e non c'è alcuna ragione per il compilatore di non usare semplicemente ciò che trova o dare un errore se non può risolvere una chiamata al metodo specifico, proprio come fa a dozzine di altre situazioni. Le funzionalità della lingua non sono caratteristiche della VM. –

0

Se T corrisponde a più vincoli, si crea un'ambiguità che non può essere risolta automaticamente. Per esempio si dispone di una classe generica con il vincolo

where T : IFirst

e un altro con il vincolo

where T : ISecond

È ora vuole T sia una classe che implementa sia IFirst e ISecond.

Calcestruzzo esempio di codice:

public interface IFirst 
{ 
    void F(); 
} 

public interface ISecond 
{ 
    void S(); 
} 

// Should the compiler pick this "overload"? 
public class My<T> where T : IFirst 
{ 
} 

// Or this one? 
public class My<T> where T : ISecond 
{ 
} 

public class Foo : IFirst, ISecond 
{ 
    public void Bar() 
    { 
     My<Foo> myFoo = new My<Foo>(); 
    } 

    public void F() { } 
    public void S() { } 
} 
+0

.. Ciò provoca una collisione del nome; nella mia domanda l'errore è causato dal fatto che il compilatore non sa quale overload di metodo scegliere per la chiamata al metodo: 'Bar (nuova Iguana(), null)'. Probabilmente sto rallentando, ma non vedo ancora la connessione tra questi due. Ho intenzione di studiare un po 'di più il tuo esempio .. – Daryl

+4

@EricJ puoi anche causare l'ambiguità del metodo senza usare i generici- la stessa situazione si verificherebbe se due overload di un metodo avessero rispettivamente 'IFirst' e' ISecond' e tu avevi provato per risolvere quale metodo chiamare con un argomento di tipo 'Foo'. Non penso che questo sia il motivo per cui il team C# ha deciso di non renderlo parte della firma del metodo. –

+0

@ChrisShain Hmm, ma se si dispone di ambiguità per la chiamata al metodo che prende IFirst e ISecond, il compilatore genererà un errore e sarà possibile risolvere il problema eseguendo il cast dell'interfaccia che si desidera. Se i vincoli generici facessero parte delle firme dei metodi avresti bisogno di una sintassi per scegliere tra diversi vincoli sul sito di chiamata, e qualsiasi modifica ai vincoli generici di una biblioteca significherebbe che il codice chiamante dovrebbe essere ricompilato per continuare a funzionare che penso sia meno ideale . –

Problemi correlati