Conversioni definite dall'utente
Aggiunga operatori di conversione impliciti ed espliciti.
Conversioni definite dall'utente è una lezione C# Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento C# Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso C# Academy include 4 lezioni in totale.
Conversioni definite dall'utente
C# consente a un tipo di definire come convertirsi in un altro tipo o da un altro tipo usando gli operatori implicit ed explicit. Le conversioni implicite avvengono automaticamente, mentre quelle esplicite richiedono un cast.
Una conversione implicita
Usi implicit operator quando una conversione è sempre sicura e non comporta perdita di informazioni. Il compilatore la applica automaticamente ovunque sia previsto il tipo di destinazione.
using System;
public struct Celsius
{
public double Degrees;
public Celsius(double d) { Degrees = d; }
// Always safe: a Celsius is just a number
public static implicit operator double(Celsius c) => c.Degrees;
}
public class Program
{
public static void Main()
{
Celsius temp = new Celsius(21.5);
double d = temp; // implicit, no cast needed
Console.WriteLine(d);
}
}Una conversione esplicita
Usi explicit operator quando una conversione può comportare una perdita di informazioni o non riuscire. Chi effettua la chiamata deve scrivere un cast, indicando di accettare il rischio.
using System;
public struct Money
{
public decimal Amount;
public Money(decimal a) { Amount = a; }
// Loses the fractional cents, so make it explicit
public static explicit operator int(Money m) => (int)m.Amount;
}
public class Program
{
public static void Main()
{
var m = new Money(19.99m);
int dollars = (int)m; // explicit cast required
Console.WriteLine(dollars);
}
}Convertire verso il proprio tipo
Le conversioni possono funzionare anche nell'altra direzione: da un altro tipo verso il proprio. In questo caso, un operatore implicit crea un Celsius a partire da un double grezzo.
using System;
public struct Celsius
{
public double Degrees;
public Celsius(double d) { Degrees = d; }
public static implicit operator Celsius(double d) => new Celsius(d);
public override string ToString() => Degrees + "C";
}
public class Program
{
public static void Main()
{
Celsius t = 18.0; // double implicitly becomes Celsius
Console.WriteLine(t);
}
}Implicita o esplicita: quale scegliere
La regola pratica è questa: renda la conversione implicita solo se non comporta mai perdita di dati e non genera mai eccezioni. Se può causare perdita di precisione, overflow o fallire, la renda esplicita.
using System;
public struct Percentage
{
public double Value; // 0..1
public Percentage(double v) { Value = v; }
// Safe and lossless -> implicit
public static implicit operator double(Percentage p) => p.Value;
// Could be out of range -> explicit
public static explicit operator Percentage(double v) => new Percentage(v);
}
public class Program
{
public static void Main()
{
double d = new Percentage(0.25);
var p = (Percentage)0.5;
Console.WriteLine(d + " " + p.Value);
}
}Conversioni tra tipi personalizzati
Le conversioni non riguardano solo i tipi incorporati. Può convertire due tipi definiti da Lei, ad esempio da coordinate polari a coordinate cartesiane.
using System;
public struct Cartesian
{
public double X, Y;
public Cartesian(double x, double y) { X = x; Y = y; }
public override string ToString() => "(" + Math.Round(X, 2) + ", " + Math.Round(Y, 2) + ")";
}
public struct Polar
{
public double R, Theta;
public Polar(double r, double theta) { R = r; Theta = theta; }
public static explicit operator Cartesian(Polar p)
=> new Cartesian(p.R * Math.Cos(p.Theta), p.R * Math.Sin(p.Theta));
}
public class Program
{
public static void Main()
{
var c = (Cartesian)new Polar(1.0, 0.0);
Console.WriteLine(c);
}
}Le conversioni si combinano con gli operatori
Una volta definita una conversione, il valore può essere usato nelle espressioni del tipo di destinazione. Una conversione implicita in double consente di usare direttamente il tipo nelle operazioni aritmetiche.
using System;
public struct Meters
{
public double Value;
public Meters(double v) { Value = v; }
public static implicit operator double(Meters m) => m.Value;
}
public class Program
{
public static void Main()
{
var distance = new Meters(5);
double doubled = distance * 2; // uses implicit conversion to double
Console.WriteLine(doubled);
}
}Evitare conversioni implicite sorprendenti
Le conversioni implicite che non sono chiaramente sicure possono nascondere bug, perché il compilatore le applica in silenzio. In caso di dubbio, preferisca quella esplicita, così l'intento risulta visibile nel codice.
using System;
public struct UserId
{
public int Value;
public UserId(int v) { Value = v; }
// Explicit on purpose: an int is not always a valid id
public static explicit operator UserId(int v) => new UserId(v);
public static explicit operator int(UserId id) => id.Value;
}
public class Program
{
public static void Main()
{
var id = (UserId)42;
int raw = (int)id;
Console.WriteLine(raw);
}
}Gli operatori di conversione sono static
Come gli altri operatori, gli operatori di conversione sono public static. Esattamente uno dei tipi coinvolti deve essere il tipo che dichiara l'operatore.
using System;
public struct Fahrenheit
{
public double Degrees;
public Fahrenheit(double d) { Degrees = d; }
public static implicit operator Fahrenheit(double d) => new Fahrenheit(d);
public static implicit operator double(Fahrenheit f) => f.Degrees;
public override string ToString() => Degrees + "F";
}
public class Program
{
public static void Main()
{
Fahrenheit f = 98.6;
double d = f;
Console.WriteLine(f + " = " + d);
}
}Un tipo wrapper pratico
Le conversioni sono particolarmente utili per i tipi wrapper leggeri, che rafforzano il sistema dei tipi senza introdurre complicazioni. Qui un NonEmptyString viene convertito implicitamente in string, ma per crearlo è necessario un cast esplicito.
using System;
public struct NonEmptyString
{
public string Value;
public NonEmptyString(string v)
{
if (string.IsNullOrEmpty(v)) throw new ArgumentException("empty");
Value = v;
}
public static explicit operator NonEmptyString(string s) => new NonEmptyString(s);
public static implicit operator string(NonEmptyString s) => s.Value;
}
public class Program
{
public static void Main()
{
var name = (NonEmptyString)"Ada";
string s = name;
Console.WriteLine(s);
}
}Provi Lei
Definisca un wrapper con una conversione implicita in uscita (sicura) e una esplicita in ingresso (convalidata). Noti quale direzione richiede un cast.
using System;
public struct Ratio
{
public double Value;
public Ratio(double v)
{
if (v < 0 || v > 1) throw new ArgumentOutOfRangeException(nameof(v));
Value = v;
}
public static implicit operator double(Ratio r) => r.Value; // always safe
public static explicit operator Ratio(double v) => new Ratio(v); // may throw
}
public class Program
{
public static void Main()
{
var half = (Ratio)0.5; // explicit, validated
double d = half; // implicit, safe
Console.WriteLine(d * 100 + "%");
}
}Verifica rapida
Scelga il tipo di conversione corretto.
Riepilogo
Le conversioni definite dall'utente consentono ai Suoi tipi di interagire in modo chiaro.
implicit operatorper conversioni sempre sicure e senza perdita di dati.explicit operatorquando si possono perdere dati o la conversione può fallire.- Le conversioni possono avere come destinazione tipi incorporati o personalizzati, in entrambe le direzioni.
- Sono
public statice vengono dichiarate da uno dei tipi coinvolti.
Domande Frequenti
La lezione «Conversioni definite dall'utente» è gratuita?
Sì — il testo completo di «Conversioni definite dall'utente» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso C# Academy, passa a CoddyKit PRO. Il corso C# Academy include 4 lezioni in totale.
Cosa imparerò in «Conversioni definite dall'utente»?
Aggiunga operatori di conversione impliciti ed espliciti. Eserciti C# Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare C# Academy?
Non è richiesta alcuna esperienza precedente. C# Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Conversioni definite dall'utente»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione C# Academy?
Sì. Ogni lezione C# Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Overload degli operatori aritmetici
- Overload degli operatori di confronto
- Conversioni definite dall'utente
- Best practice per l'overload degli operatori