è possibile ottenere la sintassi hai mostrato in questione, ma è necessario impegnarsi in abbastanza una buona quantità di intelligenza per arrivarci.
Impostiamo il problema un po 'più concretamente. Il punto chiave qui, penso, è la sintassi. Vogliamo che questo:
int intValue = GetData();
string stringValue = GetData();
DateTime[] dateTimeArrayValue = GetData();
Tuttavia, non vogliamo far funzionare tutto questo:
double doubleValue = GetData();
DateTime? nullableDateTimeValue = GetData();
Al fine di raggiungere questo obiettivo, dobbiamo usare un oggetto intermediario il valore restituito da GetData()
, la cui definizione assomiglia a questo:
public class Data
{
public int IntData { get; set; }
public string StringData { get; set; }
public DateTime[] DataTimeArrayData { get; set; }
public MultiReturnValueHelper<int, string, DateTime[]> GetData()
{
return new MultiReturnValueHelper<int, string, DateTime[]>(
this.IntData,
this.StringData,
this.DataTimeArrayData);
}
}
La tua implementazione, ovviamente, sarebbe molto diversa, ma lo farà. Ora definiamo MultiReturnValueHelper
.
public class MultiReturnValueHelper<T1, T2, T3> : Tuple<T1, T2, T3>
{
internal MultiReturnValueHelper(T1 item1, T2 item2, T3 item3)
: base(item1, item2, item3)
{
}
public static implicit operator T1(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item1;
}
public static implicit operator T2(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item2;
}
public static implicit operator T3(MultiReturnValueHelper<T1, T2, T3> source)
{
return source.Item3;
}
}
Ripetere questa definizione per T1
, T2
, T3
, ecc per il caso generico.
È anche possibile associare l'helper del valore di ritorno molto vicino alla classe o al metodo che lo restituisce, consentendo di creare questo stesso tipo di effetto per gli indicizzatori, in cui è possibile ottenere e assegnare un insieme discreto di tipi. È lì che l'ho trovato più utile.
Un'altra applicazione è quello di consentire sintassi simile alla seguente:
data["Hello"] = "World";
data["infamy"] = new DateTime(1941, 12, 7);
data[42] = "Life, the universe, and everything";
L'esatto meccanismo per raggiungere questo sintassi è lasciato come esercizio al lettore.
Per una soluzione più generale a questo problema (che è, penso, lo stesso di un problema di unione discriminato), vedere my answer to that question.
charlieday, potresti fornire qualche altro dettaglio sul motivo per cui desideri un metodo che può restituire più tipi di reso? Mi chiedo se la classe Convert nello spazio dei nomi System potrebbe essere un buon modello da seguire. Ha più metodi di conversione di diversi tipi di ritorno ma codifica il tipo restituito nel nome del metodo. Per esempio. ToBoolean, ToByte, ToChar, ecc. –
Il motivo è perché nel tuo scenario, le informazioni sul tipo sarebbero fluide "in entrambe le direzioni". Un principio di base del design del linguaggio è che dovresti essere in grado di analizzare il tipo di ogni parte di un'espressione in modo indipendente. Vogliamo essere in grado di determinare il tipo di espressione della chiamata indipendentemente da ciò a cui viene assegnato. L'eccezione a questa regola è rappresentata dalle espressioni lambda; rendere le informazioni sul tipo "flusso in entrambe le direzioni" nelle espressioni lambda era molto difficile. Vedi "metodi anonimi vs espressioni lambda" nel mio blog per i dettagli. –
si può guardare la mia risposta qui http: // StackOverflow.it/questions/1366136/overloading-on-base-of-return-only/14337184 # 14337184 –