C# Language
Tipo dinamico
Ricerca…
Osservazioni
La parola chiave dynamic
dichiara una variabile il cui tipo non è noto al momento della compilazione. Una variabile dynamic
può contenere qualsiasi valore e il tipo di valore può cambiare durante il runtime.
Come notato nel libro "Metaprogramming in .NET", C # non ha un tipo di supporto per la parola chiave dynamic
:
La funzionalità abilitata dalla parola chiave
dynamic
è un insieme intelligente di azioni del compilatore che emettono e utilizzano oggettiCallSite
nel contenitore del sito dell'ambito di esecuzione locale. Il compilatore gestisce ciò che i programmatori percepiscono come riferimenti di oggetti dinamici attraverso quelle istanze diCallSite
. I parametri, i tipi di ritorno, i campi e le proprietà che ottengono il trattamento dinamico in fase di compilazione possono essere contrassegnati con alcuni metadati per indicare che sono stati generati per l'uso dinamico, ma il tipo di dati sottostante per loro sarà sempreSystem.Object
.
Creare una variabile dinamica
dynamic foo = 123;
Console.WriteLine(foo + 234);
// 357 Console.WriteLine(foo.ToUpper())
// RuntimeBinderException, since int doesn't have a ToUpper method
foo = "123";
Console.WriteLine(foo + 234);
// 123234
Console.WriteLine(foo.ToUpper()):
// NOW A STRING
Tornando dinamico
using System;
public static void Main()
{
var value = GetValue();
Console.WriteLine(value);
// dynamics are useful!
}
private static dynamic GetValue()
{
return "dynamics are useful!";
}
Creazione di un oggetto dinamico con proprietà
using System;
using System.Dynamic;
dynamic info = new ExpandoObject();
info.Id = 123;
info.Another = 456;
Console.WriteLine(info.Another);
// 456
Console.WriteLine(info.DoesntExist);
// Throws RuntimeBinderException
Gestione di tipi specifici sconosciuti al momento della compilazione
I seguenti risultati equivalenti di output:
class IfElseExample
{
public string DebugToString(object a)
{
if (a is StringBuilder)
{
return DebugToStringInternal(a as StringBuilder);
}
else if (a is List<string>)
{
return DebugToStringInternal(a as List<string>);
}
else
{
return a.ToString();
}
}
private string DebugToStringInternal(object a)
{
// Fall Back
return a.ToString();
}
private string DebugToStringInternal(StringBuilder sb)
{
return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}";
}
private string DebugToStringInternal(List<string> list)
{
return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" + string.Join(Environment.NewLine + "\t", list.ToArray())}";
}
}
class DynamicExample
{
public string DebugToString(object a)
{
return DebugToStringInternal((dynamic)a);
}
private string DebugToStringInternal(object a)
{
// Fall Back
return a.ToString();
}
private string DebugToStringInternal(StringBuilder sb)
{
return $"StringBuilder - Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}, Value: {sb.ToString()}";
}
private string DebugToStringInternal(List<string> list)
{
return $"List<string> - Count: {list.Count}, Value: {Environment.NewLine + "\t" + string.Join(Environment.NewLine + "\t", list.ToArray())}";
}
}
Il vantaggio per la dinamica, è l'aggiunta di un nuovo tipo da gestire richiede solo l'aggiunta di un sovraccarico di DebugToStringInternal del nuovo tipo. Elimina anche la necessità di eseguirne manualmente il cast nel tipo.