Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C# / VB.NET - ritorno tipo generico
Forum - C# / VB.NET - ritorno tipo generico

Pagine: [ 1 2 ] Precedente | Prossimo
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2125
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 10:16
Martedì, 23/11/2021
Salve ragazzi, mi sto un pò confondendo con i tipi generici.
Magari non riesco a trovare una soluzione per la troppa confunsione che ho in testa :rotfl:
E qualcuno più lucido in questo momento può aiutarmi.

Niente di particolare, non riesco ad ottenere un tipo generico.
Devo fare una funzione che Accetta sia il Tipo come argomento che quello di ritorno.

esempio dovrei ottenere qualcosa del genere
(l'esempio non funziona ma è giusto per capire cosa voglio ottenere)

Codice sorgente - presumibilmente C#

  1. var ret = SendGetPacket<PacketData>(paket);
  2.  
  3.  
  4. static object SendGetPacket<T>(T type)
  5. {
  6.       object obj;
  7.  
  8.       if(type.getType() == typeof(PacketData))
  9.       {
  10.  
  11.              byte[] data = ((PacketData)type).Serialize(); //Errore Non è possibile convertire il tipo 'T' in Packet.PacketData'.      
  12.  
  13.              
  14.              if ((uint)((PacketData)paket).HeaderCommand == 0x14)
  15.              {
  16.                      PacketData r = new PacketData();
  17.                      r.Command = (uint)PacketData.HeaderCommand.ACT_LOGIN;
  18.                      r.Argument1 = p.Argument1;
  19.                      r.Argument2 = p.Argument2;
  20.  
  21.                      r.Serialize();
  22.                      client.SendPacket(r);
  23.                      obj = r;
  24.              }
  25.  
  26.        } else { //Altro }
  27.      
  28.  
  29. return obj;
  30.  
  31. }




Nell'esempio, Invio un tipo strutturato come argomento che contiene diverse informazioni e funzioni.
nello specifico PacketData che sarebbe un pacchetto strutturato con Header, Body e Footer.
che non supera i 60byte a pacchetto inviato.
Devo inviare ed in seguito ricevere un'altro pacchetto di risposta che può variare a seconda del tipo dell'informazione contenuta nell'Header. quindi il tipo di ritorno non sarà mai uguale a quello inviato.
per questo mi serve un tipo di ritorno generico e non standard.
Ma stranamente mi da errore dicendo di non poter convertire T in in PacketData o altro.
Da cosa può dipnedere?
Spero qualcuno possa darmi qualche illuminazione


Ultima modifica effettuata da Thejuster il 23/11/2021 alle 10:44


PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1023
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 14:13
Martedì, 23/11/2021
se invece di dichiarare ret come var, lo dichiari object?:

object  ret = SendGetPacket<PacketData>(paket);


in programmazione tutto è permesso
PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2125
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 16:30
Martedì, 23/11/2021
Sarebbe identico perché var è generico assume qualsiasi valore gli viene dato così come object.

il problema principale avviene qui, non e tanto il return che mi preoccupa.
Ma il fatto di non riuscire a forzare il compilatore a trasformare il tipo T Generico in PacketData

Codice sorgente - presumibilmente C# / VB.NET

  1. byte[] data = ((PacketData)type).Serialize(); //Errore Non è possibile convertire il tipo 'T' in Packet.PacketData'.




ho tentato diverse strade, così come

Codice sorgente - presumibilmente C# / VB.NET

  1. T SendGetPacket<T>(T t)
  2.         {
  3.             if(typeof(T) == typeof(PacketData))
  4.             {
  5.                 PacketData p = new PacketData();
  6.                 p.Argument1 = ((PacketData)t).Argument1;
  7.  
  8.                 //.....
  9.             }
  10.  
  11.             return t;
  12.         }



Niente da fare.

Esempio della struttura PacketData alquanto ambigua giusto per farvi un idea.

Codice sorgente - presumibilmente C#

  1. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
  2.     public struct PacketData
  3.     {
  4.         public uint Command;
  5.  
  6.         public String Argument1;
  7.  
  8.         public String Argument2;
  9.  
  10.         //ecc ecc....
  11.  
  12.     }



Cioè non sò, mi sembra assurdo che il compilatore non riesce ad indentificare una semplice struttura.
Magari... servirà una conversione implicita? non ho proprio idea di come risolvere.



Thejuster ha allegato un file: Cattura.PNG (25137 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da Thejuster il 23/11/2021 alle 16:34


PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1023
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 21:46
Martedì, 23/11/2021
Potresti controllare in debug cosa contiene il tuo t quando lo ricevi, visto che è generico prima di fare la conversione di tipo devi capire cosa contiene:

Codice sorgente - presumibilmente C# / VB.NET

  1. T SendGetPacket<T>(T t)
  2.         {
  3.             if (typeof(T) == typeof(PacketData))
  4.             {
  5.                 PacketData p = new PacketData();
  6.  
  7.                 object ot = t;
  8.  
  9.                // p.Argument1 = ((PacketData)t).Argument1;
  10.  
  11.                 //.....
  12.             }
  13.  
  14.             return t;
  15.         }




Ultima modifica effettuata da Carlo il 27/11/2021 alle 8:17


in programmazione tutto è permesso
PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2125
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 22:58
Martedì, 23/11/2021
magari potrei farlo  :rotfl:
segnandolo in rosso non ti fa partire nemmeno il debugger.


PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1023
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 14:47
Mercoledì, 24/11/2021
Testo quotato

Postato originariamente da Thejuster:

magari potrei farlo  :rotfl:
segnandolo in rosso non ti fa partire nemmeno il debugger.



Se hai visto il codice, l'istruzione che da errore l'ho remmata.
Ho aggiunto la variabile ot di tipo object, dove devi andare a vedere cosa c'è dentro.

object ot = t;

Ultima modifica effettuata da Carlo il 27/11/2021 alle 8:18


in programmazione tutto è permesso
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1023
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 20:27
Mercoledì, 24/11/2021
Risolto, dopo che hai messo il tipo generico t in un oggetto, la conversione di tipo, usando l'oggetto, non da più errore e funziona:

Codice sorgente - presumibilmente C# / VB.NET

  1. T SendGetPacket<T>(T t)
  2. {
  3.         if (typeof(T) == typeof(PacketData))
  4.         {
  5.              PacketData p = new PacketData();
  6.              object ot = t;
  7.              p.Argument1 = ((PacketData)ot).Argument1;
  8.  
  9.              //.....
  10.         }
  11. }


Ultima modifica effettuata da Carlo il 27/11/2021 alle 8:44


in programmazione tutto è permesso
PM Quote
Avatar
Thejuster (Admin)
Guru^2


Messaggi: 2125
Iscritto: 04/05/2008

Segnala al moderatore
Postato alle 12:40
Lunedì, 29/11/2021
Ninete non sò allora perché a me non funziona.

Teoricamente, questo tipo di funzione, dovrebbe servirmi a fare qualcosa del genere.

Codice sorgente - presumibilmente C# / VB.NET

  1. T SendGetPacket<T>(T t)
  2.         {
  3.             //PacketData è un Pacchetto strutturato generico
  4.            //che non richiede particolari accortenze
  5.            //Diversamente dagli altri, ha solo funzioni limitate
  6.           //di Ricezione e riposta di 2 semplici argomenti
  7.           //Argument1 e Argument2 che in seguito i valori
  8.           //vengono convertiti in base al tipo di richiesta
  9.           //Contenuto nell'header
  10.  
  11.             PacketData p = new PacketData();
  12.  
  13.             object _ret = null; //oggetto generico di ritorno
  14.  
  15.             if (typeof(T) == typeof(CharPaket)) //Se T in argomento è di tipo CharPacket
  16.             {
  17.                                
  18.                 object ot = t;
  19.                 if(((CharPaket)ot).hp <= 0) //se personaggio gli HP sono < = di 0
  20.                 {
  21.                     //Invio richiesta di Morte al server
  22.                     p.Command = (uint)PacketHeader.HeaderCommand.ACT_CHAR_DEATH;
  23.                     p.Argument1 = ((CharPaket)ot).accountID.ToString(); //Id Account
  24.                     p.Argument2 = ((CharPaket)ot).CharNum.ToString(); //Numero del personaggio nel database
  25.  
  26.                    
  27.                 }
  28.  
  29.                 _ret = p; //Assegno alla variabile object il pacchetto PacketData da ritornare
  30.  
  31.             }
  32.             return _ret;   //------------    Errore qui
  33.         }




Fatto sta, ho sempre il medesimo errore.

Non è possibile convertire in modo implicito il tipo 'object' in 'T'. È presente una conversione esplicita. Probabilmente manca un cast.

il PacketData è generico come detto nei commenti.
Se sò che l'header equivale a 0x40, il client ha inviato una richiesta di login.
quindi so per certo che l'argomento 1 contiene username e il 2 la password.
così come per gli atri vari comandi che non richiedono particolari espressioni o condizioni.

Gli altri invece è più elorabata come cosa, perché ottimizzando il tutto, senza lasciare byte a caso, o vuoti,
e senza inviare al server inutili byte, gli invio quello che servono.
Perché la struttura non può superare quella soglia di bytes per regola
impostata come dimensione fissa usando il Marshalling.
Usando strutture di tipo Sequenziali con un Layout predefitino.
So che quindi a tot byte da un range da 0 - a 20 c'è un dato ecc. ecc.
Insomma è abbastanza complicato da spiegare, ma rende l'idea di ciò che ho fatto.
Avendo prestazioni altissime e pacchetti molto leggeri e complessi che non superano i 120byte ( Non KB ma Bytes)
Sfruttando poi il .NET Core come server, è un qualcosa di spettacolare.


hmmm... 8-|

Ultima modifica effettuata da Thejuster il 29/11/2021 alle 12:58


PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 1023
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 13:57
Lunedì, 29/11/2021
Se alla riga 32 hai un errore è normale, cerchi di ritornare un oggetto quando invece hai dichiarato che la funzione deve ritornare un tipo generico T.

alla riga 32:

return (T)_ret;

Naturalmente ritornando un tipo generico, poi devi eseguire tutti i controlli del caso per estrarre il valore che ti interessa.

Personalmente cambierei la funzione in:

object SendGetPacket<T>(T t)

Visto che il tipo generico al ritorno non ti serve più, fai la tua scelta...

Se invece sei certo che restituisci sempre un PaketData, per evitare sempre gli stessi controlli e conversioni di tipo:

Codice sorgente - presumibilmente C#

  1. PacketData SendGetPacket<T>(T t)
  2. {
  3.   //PacketData è un Pacchetto strutturato generico
  4.   //che non richiede particolari accortenze
  5.   //Diversamente dagli altri, ha solo funzioni limitate
  6.   //di Ricezione e riposta di 2 semplici argomenti
  7.   //Argument1 e Argument2 che in seguito i valori
  8.   //vengono convertiti in base al tipo di richiesta
  9.   //Contenuto nell'header
  10.      
  11.         PacketData p = new PacketData();
  12.      
  13.         if (typeof(T) == typeof(CharPaket)) //Se T in argomento è di tipo CharPacket
  14.         {
  15.               object ot = t;
  16.               if(((CharPaket)ot).hp <= 0) //se personaggio gli HP sono < = di 0
  17.               {
  18.                   //Invio richiesta di Morte al server
  19.                   p.Command = (uint)PacketHeader.HeaderCommand.ACT_CHAR_DEATH;
  20.                   p.Argument1 = ((CharPaket)ot).accountID.ToString(); //Id Account
  21.                   p.Argument2 = ((CharPaket)ot).CharNum.ToString(); //Numero del personaggio nel database
  22.               }
  23.         }
  24.         return p;  
  25. }


Ultima modifica effettuata da Carlo il 29/11/2021 alle 15:02


in programmazione tutto è permesso
PM Quote
Pagine: [ 1 2 ] Precedente | Prossimo