Domanda

Ho una classe che contiene due metodi come questi:

public String getFoo(Int32 a)
{
  return getBar(a, "b", null);
}

public String getBar(Int32 a, String b, Int32 c)
{
  //do something
  return "";
}

Tuttavia quando compilo la mia classe ottengo due errori:

  1. La migliore corrispondenza del metodo con overload per getBar (int, string, int) ha alcuni argomenti non validi
  2. Argomento '3': impossibile convertire da '<null>' a 'int'

Penso di capire perché sto ricevendo questo errore: il compilatore non lo sa al momento della compilazione qual è il tipo reale dell'oggetto. Qualcuno può confermare se ho ragione sulla causa dell'errore o indicare il vero motivo?

Ancora più importante, posso progettare il mio codice in questo modo? In tal caso, cosa devo fare per correggere gli errori? La mia ragione per progettare la mia classe in questo modo è perché non voglio duplicare il codice in getBar, in getFoo. I due metodi fanno essenzialmente la stessa cosa tranne uno prende un terzo parametro.

Grazie.

È stato utile?

Soluzione

In .NET esiste un concetto distinto tra tipi di riferimento e tipi di valore.

Un tipo di riferimento è un oggetto allocato sull'heap (sarà una sottoclasse di System.Object). Tutto ciò che è nello stack è un puntatore a questo oggetto. Per questo motivo, è perfettamente valido memorizzare un puntatore null.

Un tipo di valore è un oggetto allocato nello stack, sarà una sottoclasse di System.ValueType. Poiché un tipo di valore vive nello stack, quando si passa il suo valore a una funzione, si passa l'intero contenuto dell'oggetto.

I tipi di valore non possono essere nulli.

La maggior parte dei tipi primitivi C # sono tipi di valore. String è un tipo speciale di primitiva che in realtà è un tipo di riferimento.

In .NET 2.0, MS ha aggiunto la possibilità di racchiudere un tipo generico all'interno di una struttura in modo da poter simulare un tipo nullable. Ciò che realmente accade è che la logica all'interno della Nullable & Lt; T & Gt; struct sta emulando un valore nullo per te.

Lo hanno espresso usando un collegamento alla sintassi aggiungendo un punto interrogativo al tipo, ad esempio:

int? nullableInt = null;
float? nullableFloat = null;

ecc ...

Se non ti piace l'int? sintassi, puoi sempre usare Nullable < SomeType >

public String getBar(Int32 a, String b, Nullable<Int32> c)

Come nota a margine, preferisco aggiungere un sovraccarico quando fai quello che stai facendo, solo per rendere più bella la sintassi.

public String getBar(Int32 a, String b)
{
     this.getBar(a,b,null);
}

public String getBar(Int32 a, String b, Nullable<Int32> c)
{
}

Altri suggerimenti

Prova a trasformare il terzo argomento in getBar int nullable.

Quindi, la firma sarebbe simile a questa:

public String getBar(Int32 a, String b, Int32? c)

Puoi trovare ulteriori informazioni sui tipi nullable in .NET qui e qui .

Int32 è un tipo di valore, il che significa che null non è un argomento valido per i parametri di tipo int?.

Se hai davvero bisogno di inseribili nullable, usa il tipo <=>.

I due errori visualizzati sono in realtà lo stesso errore.

Sunny è corretto.
Int32 è un tipo di valore e non può contenere il valore "null". Se devi passare "null" come valore di parametro, utilizza Nullable invece di Int32 come tipo di argomento.

Puoi trovare ulteriori informazioni su Tipi nullabili (C # Guida alla programmazione) su MSDN.

Int32 è un alias per int che è un tipo valore / non annullabile. Per una versione nullable usa System.Nullable o semplicemente 'int?'.

Inoltre, non dimenticare di convertire nuovamente in un int non annullabile:

int? nullable = ...;
int non_nullable = nullable??0; 

dove il numero indica quale valore dovrebbe assumere se è effettivamente nullo.

Int32 non può essere nullo. Rendi invece un tipo nullable:

public String getBar(Int32 a, String b, Int32? c)
{
    if (c.HasValue)
    {
        ...do something with c.Value...
    }
    return "";
}

OK, quindi cinque sette persone hanno proposto int? come soluzione. Propongo altre due soluzioni che potrebbe essere più appropriate, a seconda della situazione;

  • Crea un sovraccarico del metodo che ha solo due argomenti e ometti null quando chiami:

    public String getFoo(Int32 a)
    {
      return getBar(a, "b", null);
    }
    
    public String getBar(Int32 a, String b)
    {
      //do something else, without the int
    }
    

    Anche se probabilmente non vuoi farlo poiché hai dichiarato di voler evitare la duplicazione del codice.

  • Usa default invece di 0 :

    return getBar(a, "b", default(int));
    

    Per inciso, questo equivale a passare il valore <=>.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top