20 messaggi dal 06 settembre 2014
Mi sto ritrovando a studiarele interfacce..la teoria sinceramente non la sto capendo molto bene ultimamente..

Mi ritrovo con questo esempio:

public static T Max<T> (IEnumerable<T> list) where T: IComparable
{
bool isFirst = true;

T res= default(T);
foreach (T item in list)
{
if(isFirst)
{
res = item;
isFirst = false;
}
if (res.CompareTo(item) < 0)
res= item;
}
return res;
}


Cosa sarebbe quel Max<T>?
L'argomento del metodo cosa significa?

Forse sbaglio io, o forse il libro.. stavo studiando come impostare dei vincoli sui tipi generici, ma in ogni esempio leggo cose nuove e non ci capisco molto.

Quando scrivono
T res= default(T);


significa che a T assegnano il nome res e danno il valore default?

Quando assegnano il nome a T, assegnerebbero il nome alla T di Max<T>? Quella dentro alla "parentesi"?
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,

cricchi ha scritto:

significa che a T assegnano il nome res e danno il valore default?

No, dunque: Max è un metodo generico e ciò vuol dire che la sua logica può funzionare su oggetti di un tipo arbitrario T, come per esempio string, int, Persona o altro.

In realtà, nel caso di Max, il tipo non può essere uno qualsiasi, perché è stato definito un vincolo ben preciso: consente solo i tipi che implementano l'interfaccia IComparable e questo include string e int, ma non Persona.

Se osservi il parametro di Max, noterai che è di tipo IEnumerable<T>, cioè accetta un elenco di quei tipi di cui abbiamo appena parlato.

Il programmatore che voglia usare il metodo Max<T>, dovrà quindi:
  • Scegliere il tipo che vuole usare al posto di T (es. string)
  • Passare al metodo Max un elenco di oggetti del tipo scelto.


Ecco quindi un esempio di invocazione del metodo:
//definisco un array di stringhe. Questo sarà l'"elenco di stringhe" che passerò a Max
string[] elenco = new string[] {"A", "B", "C"};
//passare come argomento un array di stringhe va bene, perché l'array implementa IEnumerable
string risultato = Max<string>(elenco);

Oppure, per brevità posso scrivere:
//posso omettere <string> perché il compilatore è in grado di inferire dall'argomento il tipo che ho scelto
string risultato = Max(elenco);


Per capire meglio il senso del metodo Max, fai finta che al posto di T ci sia scritto string, o comunque qualsiasi tipo che implementi IComparable. T è solo un parametro di tipo, che a runtime verrà sostituito dal tipo concreto scelto dallo sviluppatore.

Il T non è una parola chiave. Potevi usare qualsiasi altro nome con lo stesso criterio con cui scegli il nome di una variabile, ma la linea guida vuole che i parametri di tipo - per lo meno - inizino con T.

Detto questo, arrivo alla tua domanda:

Quando scrivono
T res= default(T);


Se lo sviluppatore aveva scelto string, puoi leggere quella linea come:
string res = default(string);
Il default(string) qui serve soltanto ad inizializzare la variabile res con un valore di default che, nel caso di string come degli altri reference types, è il null.

Il default è necessario perché chi ha scritto il metodo Max consente di usare anche value types come int, che invece non possono essere inizializzati a null. Il default quindi restituisce un valore opportuno e compatibile con il tipo su cui agisce.
Ecco la documentazione:
http://msdn.microsoft.com/en-us/library/xwth0h0d.aspx

ciao,
Moreno
Modificato da BrightSoul il 27 settembre 2014 21.16 -

Enjoy learning and just keep making
20 messaggi dal 06 settembre 2014
Mi da errore il compilatore a Max<TStringa>.
Ecco il codice:
public static TStringa Max<TStringa> (IEnumerable<TStringa> lista) 
        {
           string[] stringa = new string[] {"A", "B", "C"}; 
           string risultato = Max<string>(stringa);

           
                
        }


L'errore è:Non tutti i percorsi del codice restituiscono un valore.
Anche se gli davo come valore Default,nell'esempio che mi avevi fatto te, l'errore rimane.

Una domanda: quando scrivo public static TStringa Max<TStringa>, il nome del metodo che creo, deve essere anche lo stesso nome nel metodo Max? Per farti capire meglio, potevo scrivere anche così volendo:
public static Prova Max<Stringa>


Oppure darebbe errore perché i valori devono essere uguali?
11.886 messaggi dal 09 febbraio 2002
Contributi
ciao,

cricchi ha scritto:

Mi da errore il compilatore a Max<TStringa>.

Aspetta, il mio codice serviva ad invocare il metodo Max, non andava sostituito al suo corpo.

Ripristina il metodo Max com'era prima, e poi invocalo dal Main, come vedi in questo esempio:
https://dotnetfiddle.net/g9SJur

Apro parentesi: questo esempio serve solo per imparare. Sappi che Max è un metodo generico che già esiste nel framework .NET come extension method di IEnumerable<T>
http://msdn.microsoft.com/en-us/library/vstudio/bb918740(v=vs.90).aspx


Una domanda: quando scrivo public static TStringa Max<TStringa>, il nome del metodo che creo, deve essere anche lo stesso nome nel metodo Max?

No, il nome del metodo è Max. TStringa è il tipo di dato restituito dal metodo Max. Facciamo il breakdown della definizione di questo metodo:
public static T Max<T> (IEnumerable<T> lista) where T : IComparable
  • public è un modificatore di accesso che rende il metodo visibile anche dall'esterno della classe
  • static lo sviluppatore che usa il metodo non dovrà crearsi un'istanza della classe per poterlo usare, ma lo invocherà scrivendo NomeClasse.NomeMetodo(argomenti)
  • T] rapprenta il tipo di valore restituito dal metodo. Se il metodo non avesse restituito nulla, qui avremmo trovato scritto void. Se avesse restituito una stringa, avremmo trovato scritto string, e così via. Invece c'è T, vuol dire che il metodo generico restituirà lo stesso tipo di dato che lo sviluppatore avrà indicato durante l'invocazione.
  • Max è il nome del metodo
  • <T> è il parametro generico che lo sviluppatore deve definire durante l'invocazione. Se lo sviluppatore invocasse Max<string>(), allora il tipo sarebbe string. Ne consegue che anche il valore di ritorno sarebbe T, cioè string, perché T non è altro che un segnaposto per un tipo definito dallo sviluppatore.
  • (IEnumerable<T> lista) tra le parentesi troviamo i parametri del metodo. In questo caso c'è un solo parametro chiamato lista di tipo IEnumerable<T>. Se l'invocazione era avvenuta come Max<string>() allora a runtime questo parametero si configurerà come IEnumerable<string>
  • where T : IComparable questa è una restrizione sul tipo T. Lo sviluppatore non potrà invocare Max indicando un tipo qualsiasi, ma dovrà quanto meno essere un tipo che implementa l'interfaccia IComparable.


Per il momento impratichisciti con la definizione e l'uso di metodi non generici. Forse questo è già un argomento avanzato.

ciao,
Moreno
Modificato da BrightSoul il 30 settembre 2014 08.05 -

Enjoy learning and just keep making

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.