Tip
public static TTarget Convert<TTarget>(
this Object? obj,
CultureInfo culture = null
)
<ExtensionAttribute>
Public Shared Function Convert(Of TTarget) (
obj As Object,
Optional culture As CultureInfo = Nothing
) As TTarget
public:
[ExtensionAttribute]
generic<typename TTarget>
static TTarget Convert(
Object^ obj,
CultureInfo^ culture = nullptr
)
[<ExtensionAttribute>]
static member Convert :
obj : Object *
?culture : CultureInfo
(* Defaults:
let _culture = defaultArg culture null
*)
-> 'TTarget
The method firstly tries to use registered direct conversions between source and target types, then attempts to perform the conversion via IConvertible types and registered TypeConverters. If these attempts fail, then the registered conversions tried to be used for intermediate steps, if possible. As an ultimate fallback, the String type is attempted to be used as intermediate conversion.
New conversions can be registered by the RegisterConversion extension methods.
A TypeConverter can be registered by the RegisterTypeConverter extension method.
TTarget can be even a collection type if obj is also an IEnumerable implementation. The target collection type must have either a default constructor or a constructor that can accept a list, array or dictionary as an initializer collection.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using KGySoft.CoreLibraries;
public class Example
{
public static void Main()
{
// between convertible types: like the Convert class but supports also enums in both ways
ConvertTo<int>("123"); // culture can be specified, default is InvariantCulture
ConvertTo<float>(ConsoleColor.Blue);
ConvertTo<ConsoleColor>(13); // this would fail by Convert.ChangeType
// TypeConverters are used if possible:
ConvertTo<Guid>("AADC78003DAB4906826EFD8B2D5CF33D");
// As a fallback, string is used as an intermediate step
ConvertTo<DateTimeOffset>(DateTime.Now); // DateTime -> string -> DateTimeOffset
// Collection conversion is also supported:
ConvertTo<bool[]>(new List<int> { 1, 0, 0, 1 });
ConvertTo<List<int>>("Blah"); // works because string is an IEnumerable<char>
ConvertTo<string>(new[] { 'h', 'e', 'l', 'l', 'o' }); // because string has a char[] constructor
ConvertTo<ReadOnlyCollection<string>>(new[] { 1.0m, 2, -1 }); // via the IList<T> constructor
// even between non-generic collections:
ConvertTo<ArrayList>(new HashSet<int> { 1, 2, 3 });
ConvertTo<Dictionary<ConsoleColor, string>>(new Hashtable { { 1, "One" }, { "Black", 'x' } });
// New conversions can be registered:
ConvertTo<long>(DateTime.Now); // fail
typeof(DateTime).RegisterConversion(typeof(long), (obj, type, culture) => ((DateTime)obj).Ticks);
ConvertTo<long>(DateTime.Now); // success
// Registered conversions can be used as intermediate steps:
ConvertTo<double>(DateTime.Now); // DateTime -> long -> double
}
private static void ConvertTo<T>(object source)
{
Console.Write($"{source.GetType().GetName(TypeNameKind.ShortName)} => {typeof(T).GetName(TypeNameKind.ShortName)}: {AsString(source)} => ");
try
{
T result = source.Convert<T>(); // a culture can be specified here for string conversions
Console.WriteLine(AsString(result));
}
catch (Exception e)
{
Console.WriteLine(e.Message.Replace(Environment.NewLine, " "));
}
}
private static string AsString(object obj)
{
if (obj == null)
return "<null>";
// KeyValuePair has a similar ToString to this one
if (obj is DictionaryEntry de)
return $"[{de.Key}, {de.Value}]";
if (obj is not IEnumerable || obj is string)
return obj.ToString();
return ((IEnumerable)obj).Cast<object>().Select(AsString).Join(", ");
}
}
// This example produces the following output:
// String => Int32: 123 => 123
// ConsoleColor => Single: Blue => 9
// Int32 => ConsoleColor: 13 => Magenta
// String => Guid: AADC78003DAB4906826EFD8B2D5CF33D => aadc7800-3dab-4906-826e-fd8b2d5cf33d
// DateTime => DateTimeOffset: 10/11/2021 7:45:46 PM => 10/11/2021 7:45:46 PM +02:00
// List`1[Int32] => Boolean[]: 1, 0, 0, 1 => True, False, False, True
// String => List`1[Int32]: Blah => 66, 108, 97, 104
// Char[] => String: h, e, l, l, o => hello
// Decimal[] => ReadOnlyCollection`1[String]: 1.0, 2, -1 => 1.0, 2, -1
// HashSet`1[Int32] => ArrayList: 1, 2, 3 => 1, 2, 3
// Hashtable => Dictionary`2[ConsoleColor,String]: [1, One], [Black, x] => [DarkBlue, One], [Black, x]
// DateTime => Int64: 10/11/2021 7:45:46 PM => The specified argument cannot be converted to type System.Int64. Parameter name: obj
// DateTime => Int64: 10/11/2021 7:45:46 PM => 637695783464721787
// DateTime => Double: 10/11/2021 7:45:46 PM => 6.37695783464721787E+17
ArgumentException | obj cannot be converted to TTarget. |