Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308

    [C#] indeterminazione del tipo

    Ciao a tutti ragazzi, in particolare Oregon, Scara e Alka che è un sacco che non li sento....
    Ho un problemino(one) che mi impedisce di andare avanti nei miei viaggi spaziali con Xna, una specie di effetto quantistico (non sto scherzando).

    Creo un hashtable
    codice:
    public static Hashtable myhash = new Hashtable();
    Lo riempo con un elemento di tipo int
    codice:
    myhash.Add("A", 1);
    Dopodichè voglio eseguire questa sub (si chiama Q proprio perchè data la mia grande ignoranza in C# rappresenta una indeterminazione quantistica):
    codice:
    // k è la chiave, x un numero reale qualsiasi
    public void Q(string k, float x)  
    {
            if (myhash[k].GetType().ToString() == "System.Int32")
            {
                    int K = (int)myhash[k];
                    if (x < 1f)
                    {
                           myhash.Remove(k);
                           myhash.Add(k, "uno");
                    }
             {
            else // se non è int è string
            {
                    string K = (string)myhash[k];
                    if (x > 1f)
                    {
                           myhash.Remove(k);
                           myhash.Add(k, 1);
                    }
            }
    }
    Se applico la sub

    Q("A", 10f)

    allora myhash["A"] diventa 1, mentre con

    Q("A", 0.3f)

    myhash["A"] diventa "uno". Il caso x=1f non mi interessa.

    DDDDOMANDA: come faccio a "estrarre" l'oggetto (int o string) K dalla sub? Se sono dentro la sub Q, K è a disposizione, lo vedo e posso sapere tutto di lui, ma se sono "fuori dalla scatola Q" non posso vedere K, so solo che o è int o è string, una sovrapposizione di stati quantici (che vi dicevo?)
    Se scrivi la Q come funzione devo specificare il tipo restituito ma è proprio quello che non so; se scrivo Q come sub e gli faccio passare un parametro con 'ref' o 'out' o che so io quale diavoleria, devo lo stesso indicare in firma il suo tipo ma è proprio quello che non so.
    Dunque?
    Grazie a tutti.

  2. #2
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    è una delle soluzioni

    codice:
    public object Q(string k, float x)  
    {
      ...
      return K;
    }
    
    object val = Q(k, x);
    int intVal;
    if (int.TryParse(val, out intVal))
      //intVal è K convertito in intero
    else
      //val è una stringa puoi usarlo effettuando il cast a stringa o con val.ToString(), non fa differenza.

  3. #3
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Intanto molte grazie, rsdpzed, per la risposta (non ci speravo più).
    Purtroppo, anche se la tua risposta è adeguata alla domanda per come l'ho posta io, il problema è che il metodo TryParse si può applicare solo a tipi primitivi. Nell'esempio che ho fatto, per semplicità di esposizione, ho usato i due tipi "base" int e string; in verità i due tipi che costituiscono la "sovrapposizione di stati" per l'oggetto K sono due strutture definite da me, per le quali non credo che funzioni TryParse. Però mi hai dato qualche idea su cui lavorare...
    Grazie
    Grazie
    Grazie
    Grazie

  4. #4
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    la base di questo sistema non cambia. se hai degli oggetti invece che tipi primitivi puoi provare a fare il cast, basandoti sul fatto che un cast fallito ritorna null.

    codice:
    object o = Q(k, x);
    
    if ((o as Tipo1) != null)
      //o è di tipo Tipo1
    if ((o as Tipo2) != null)
      //o è di tipo 2
    //ecc..
    un approccio piu oop (visto che usi dei tipi definiti da te) è quello di usare un tipo base con metodi e proprietà base ridefinibili dai tipi derivati. L'importante è che tutto quello che puoi fare con i tipi derivati puoi farlo richiamando i metodi e le proprietà della classe base.

    codice:
    Base b = Q(k, x);
    
    //lavori direttamente su b senza sapere il tipo derivato per esempio:
    b.Metodo(1);
    var ris = b.Funzione();
    Metodo e funzione sono definite virtual o abstract nella classe Base e vengono ridefiniti nelle derivate. Questo è possibile, ripeto, solo se riesci a trovare un "punto di incontro" tra tutte le classi derivate in modo da poter generalizzare un interfaccia o una classe base (Base).
    Il vantaggio di questo metodo è quello di evitarti la catena di if (cast) del primo approccio.


  5. #5
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Approfitto della tua gentile disponibilità e ti descrivo i dettagli, seppure limitati allo scopo. Io ho creato due strutture

    public struct Far
    {
    ....
    }

    public struct Near
    {
    ....
    }

    L'hashtable che ho creato ospita inizialmente elementi di tipo Far. Nel corso di Update() in un game gli oggetti dell'hashtable sono continuamente rimossi e ricreati cambiando tipo in base a certe condizioni. Un certo elemento da Far diventa Near o viceversa. Nei dettagli, inizialmente io sono lontano da tutti gli ogegtti dei h (che sarebbe il mio hashtable). Dato un oggetto h[k] se mi avvicino troppo a lui succede questo

    h.Remove(k)
    h.Add(k, new Near(....)

    se invece mi allontano troppo

    h.Remove(k)
    h.Add(k, new Far(....)

    Se in Update voglio sapere qualcosa di un oggetto, per esempio dell'oggetto h["A"], in generale in qualsiasi momento non so di che tipo è questo elemento. Per saperlo devo fare

    if(h[k].GetType().ToString() == "Far")
    {
    Far x = (Far)h[k]
    ....... esploro x
    }
    else
    {
    Near x = (Near)h[k]
    ....... esploro x
    }

    Quindi x è "chiuso" dentro il blocco (la "scatola") if.... che è "doppia" e per esplorare x devo scrivere due codici identici e questo mi scoccia. Se riesco a "tirare" fuori l'oggetto x posso esplorarlo in Update con un unico codice. Mi occorre l'oggetto x nel flusso principale di Update, praticamente dopo la sua prima parentesi {

    protected override void Update(GameTime gametime)
    {
    x = h["A"]

    ...... esploro x

    Riesco a "tirare fuori" x dalla scatola solo come object, ma con questo tipo perdo tutte le proprietà di x (i suoi campi) che vorrei esplorare, perchè il tipo object non li riconosce. Ne segue che x non può essere nè var nè object. E' un principio di indeterminazione inviolabile?
    Ciao e grazie.

  6. #6
    Utente di HTML.it L'avatar di rsdpzed
    Registrato dal
    Aug 2001
    Messaggi
    764
    se non vuoi scrivere due volte lo stesso codice (ma potrebbero essere anche di piu se si vogliono per esempio, gestire piu range di distanza) allora l'unico modo è seguire il secondo sistema che ti ho suggerito.

  7. #7
    Utente di HTML.it L'avatar di escocat
    Registrato dal
    Feb 2012
    Messaggi
    308
    Eh, se mi chiamassi rsdpzed farei come dici.
    Interpretando però le tue parole (molte volte una risposta anche se non la capisci ti apre la mente) io in effetti potre "estrarre" l'oggetto facendone una "copia immaginaria" scegliendo uno dei due tipi (Near o Far). Tanto a me che mi frega se l'oggetto chiuso nella scatola è di tipo Near o Far? A me interessa conoscere i valori dei suoi campi. Se dentro la "scatola" (in cui vedo bene l'oggetto x) mi creo una copia y = new Far (x.questo, x.quello, ...) e posso farlo perchè Near e Far sono due tipi in cui x "oscilla", e faccio l'out di y, mi trovo fuori dalla scatola un oggetto y immagine perfetta di x, che differisce al più solo per il tipo, ma che per il resto ha gli stessi campi.
    Ci lavoro un pò su e poi ti dico....

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.