diff --git a/src/Microsoft.VisualBasic/ref/Microsoft.VisualBasic.cs b/src/Microsoft.VisualBasic/ref/Microsoft.VisualBasic.cs index 51430cec1447..83c4fafa8017 100644 --- a/src/Microsoft.VisualBasic/ref/Microsoft.VisualBasic.cs +++ b/src/Microsoft.VisualBasic/ref/Microsoft.VisualBasic.cs @@ -5,8 +5,6 @@ // Changes to this file must follow the http://aka.ms/api-review process. // ------------------------------------------------------------------------------ -using System; - namespace Microsoft.VisualBasic { public enum CallType @@ -46,11 +44,6 @@ void System.Collections.IList.RemoveAt(int index) { } public void Remove(int Index) { } public void Remove(string Key) { } } - public enum CompareMethod - { - Binary = 0, - Text = 1, - } [System.AttributeUsageAttribute((System.AttributeTargets)(4), Inherited=false, AllowMultiple=false)] public sealed partial class ComClassAttribute : System.Attribute { @@ -63,11 +56,17 @@ public ComClassAttribute(string _ClassID, string _InterfaceID, string _EventId) public string InterfaceID { get { throw null; } } public bool InterfaceShadows { get { throw null; } set { } } } + public enum CompareMethod + { + Binary = 0, + Text = 1, + } [Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute] public sealed partial class Constants { internal Constants() { } public const string vbBack = "\b"; + public const Microsoft.VisualBasic.CompareMethod vbBinaryCompare = Microsoft.VisualBasic.CompareMethod.Binary; public const string vbCr = "\r"; public const string vbCrLf = "\r\n"; public const string vbFormFeed = "\f"; @@ -77,9 +76,8 @@ internal Constants() { } public const string vbNullChar = "\0"; public const string vbNullString = null; public const string vbTab = "\t"; + public const Microsoft.VisualBasic.CompareMethod vbTextCompare = Microsoft.VisualBasic.CompareMethod.Text; public const string vbVerticalTab = "\v"; - public const CompareMethod vbBinaryCompare = CompareMethod.Binary; - public const CompareMethod vbTextCompare = CompareMethod.Text; } public sealed partial class ControlChars { @@ -99,8 +97,8 @@ public ControlChars() { } public sealed partial class DateAndTime { internal DateAndTime() { } - public static DateTime Now { get; } - public static DateTime Today { get; } + public static System.DateTime Now { get { throw null; } } + public static System.DateTime Today { get { throw null; } } } [System.AttributeUsageAttribute((System.AttributeTargets)(4), AllowMultiple=false, Inherited=false)] [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] @@ -108,16 +106,6 @@ public sealed partial class HideModuleNameAttribute : System.Attribute { public HideModuleNameAttribute() { } } - [System.AttributeUsageAttribute((System.AttributeTargets)(4), AllowMultiple=false, Inherited=false)] - [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(2))] - public sealed partial class MyGroupCollectionAttribute : System.Attribute - { - public MyGroupCollectionAttribute(string typeToCollect, string createInstanceMethodName, string disposeInstanceMethodName, string defaultInstanceAlias) { } - public string CreateMethod { get { throw null; } } - public string DefaultInstanceAlias { get { throw null; } } - public string DisposeMethod { get { throw null; } } - public string MyGroupName { get { throw null; } } - } [Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute] public sealed partial class Information { @@ -134,9 +122,19 @@ internal Information() { } public static int RGB(int Red, int Green, int Blue) { throw null; } public static string SystemTypeName(string VbName) { throw null; } public static int UBound(System.Array Array, int Rank = 1) { throw null; } - public static VariantType VarType(object VarName) { throw null; } + public static Microsoft.VisualBasic.VariantType VarType(object VarName) { throw null; } public static string VbTypeName(string UrtName) { throw null; } } + [System.AttributeUsageAttribute((System.AttributeTargets)(4), AllowMultiple=false, Inherited=false)] + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(2))] + public sealed partial class MyGroupCollectionAttribute : System.Attribute + { + public MyGroupCollectionAttribute(string typeToCollect, string createInstanceMethodName, string disposeInstanceMethodName, string defaultInstanceAlias) { } + public string CreateMethod { get { throw null; } } + public string DefaultInstanceAlias { get { throw null; } } + public string DisposeMethod { get { throw null; } } + public string MyGroupName { get { throw null; } } + } [Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute] public sealed partial class Strings { @@ -147,8 +145,8 @@ internal Strings() { } public static int AscW(string String) { throw null; } public static char Chr(int CharCode) { throw null; } public static char ChrW(int CharCode) { throw null; } - public static string[] Filter(object[] Source, string Match, bool Include = true, [Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute] CompareMethod Compare = CompareMethod.Binary) { throw null; } - public static string[] Filter(string[] Source, string Match, bool Include = true, [Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute] CompareMethod Compare = CompareMethod.Binary) { throw null; } + public static string[] Filter(object[] Source, string Match, bool Include = true, [Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute]Microsoft.VisualBasic.CompareMethod Compare = (Microsoft.VisualBasic.CompareMethod)(0)) { throw null; } + public static string[] Filter(string[] Source, string Match, bool Include = true, [Microsoft.VisualBasic.CompilerServices.OptionCompareAttribute]Microsoft.VisualBasic.CompareMethod Compare = (Microsoft.VisualBasic.CompareMethod)(0)) { throw null; } public static string Left(string str, int Length) { throw null; } public static string LTrim(string str) { throw null; } public static string Mid(string str, int Start) { throw null; } @@ -232,6 +230,11 @@ public sealed partial class Conversions { internal Conversions() { } public static object ChangeType(object Expression, System.Type TargetType) { throw null; } + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackUserDefinedConversion(object Expression, System.Type TargetType) { throw null; } + public static string FromCharAndCount(char Value, int Count) { throw null; } + public static string FromCharArray(char[] Value) { throw null; } + public static string FromCharArraySubset(char[] Value, int StartIndex, int Length) { throw null; } public static bool ToBoolean(object Value) { throw null; } public static bool ToBoolean(string Value) { throw null; } public static byte ToByte(object Value) { throw null; } @@ -265,12 +268,15 @@ internal Conversions() { } public static string ToString(char Value) { throw null; } public static string ToString(System.DateTime Value) { throw null; } public static string ToString(decimal Value) { throw null; } + public static string ToString(decimal Value, System.Globalization.NumberFormatInfo NumberFormat) { throw null; } public static string ToString(double Value) { throw null; } + public static string ToString(double Value, System.Globalization.NumberFormatInfo NumberFormat) { throw null; } public static string ToString(short Value) { throw null; } public static string ToString(int Value) { throw null; } public static string ToString(long Value) { throw null; } public static string ToString(object Value) { throw null; } public static string ToString(float Value) { throw null; } + public static string ToString(float Value, System.Globalization.NumberFormatInfo NumberFormat) { throw null; } [System.CLSCompliantAttribute(false)] public static string ToString(uint Value) { throw null; } [System.CLSCompliantAttribute(false)] @@ -292,8 +298,8 @@ internal Conversions() { } public sealed partial class BooleanType { internal BooleanType() { } - public static Boolean FromObject(object Value) { throw null; } - public static Boolean FromString(string Value) { throw null; } + public static System.Boolean FromObject(object Value) { throw null; } + public static System.Boolean FromString(string Value) { throw null; } } [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] public sealed partial class DecimalType @@ -332,8 +338,36 @@ public IncompleteInitialization() { } public sealed partial class NewLateBinding { internal NewLateBinding() { } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackCall(object Instance, string MemberName, object[] Arguments, string[] ArgumentNames, bool IgnoreReturn) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackGet(object Instance, string MemberName, object[] Arguments, string[] ArgumentNames) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static void FallbackIndexSet(object Instance, object[] Arguments, string[] ArgumentNames) { } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static void FallbackIndexSetComplex(object Instance, object[] Arguments, string[] ArgumentNames, bool OptimisticSet, bool RValueBase) { } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackInvokeDefault1(object Instance, object[] Arguments, string[] ArgumentNames, bool ReportErrors) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackInvokeDefault2(object Instance, object[] Arguments, string[] ArgumentNames, bool ReportErrors) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static void FallbackSet(object Instance, string MemberName, object[] Arguments) { } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + [System.ObsoleteAttribute("do not use this method", true)] + public static void FallbackSetComplex(object Instance, string MemberName, object[] Arguments, bool OptimisticSet, bool RValueBase) { } public static object LateCall(object Instance, System.Type Type, string MemberName, object[] Arguments, string[] ArgumentNames, System.Type[] TypeArguments, bool[] CopyBack, bool IgnoreReturn) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + public static object LateCallInvokeDefault(object Instance, object[] Arguments, string[] ArgumentNames, bool ReportErrors) { throw null; } public static object LateGet(object Instance, System.Type Type, string MemberName, object[] Arguments, string[] ArgumentNames, System.Type[] TypeArguments, bool[] CopyBack) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute((System.ComponentModel.EditorBrowsableState)(1))] + public static object LateGetInvokeDefault(object Instance, object[] Arguments, string[] ArgumentNames, bool ReportErrors) { throw null; } public static object LateIndexGet(object Instance, object[] Arguments, string[] ArgumentNames) { throw null; } public static void LateIndexSet(object Instance, object[] Arguments, string[] ArgumentNames) { } public static void LateIndexSetComplex(object Instance, object[] Arguments, string[] ArgumentNames, bool OptimisticSet, bool RValueBase) { } @@ -379,6 +413,8 @@ internal Operators() { } public static bool ConditionalCompareObjectNotEqual(object Left, object Right, bool TextCompare) { throw null; } public static object DivideObject(object Left, object Right) { throw null; } public static object ExponentObject(object Left, object Right) { throw null; } + [System.ObsoleteAttribute("do not use this method", true)] + public static object FallbackInvokeUserDefinedOperator(object vbOp, object[] arguments) { throw null; } public static object IntDivideObject(object Left, object Right) { throw null; } public static object LeftShiftObject(object Operand, object Amount) { throw null; } public static object ModObject(object Left, object Right) { throw null; } diff --git a/src/Microsoft.VisualBasic/src/Microsoft/VisualBasic/CompilerServices/Conversions.vb b/src/Microsoft.VisualBasic/src/Microsoft/VisualBasic/CompilerServices/Conversions.vb index 0005d338fdf0..cbdfa1991eb0 100644 --- a/src/Microsoft.VisualBasic/src/Microsoft/VisualBasic/CompilerServices/Conversions.vb +++ b/src/Microsoft.VisualBasic/src/Microsoft/VisualBasic/CompilerServices/Conversions.vb @@ -4,596 +4,1530 @@ Imports System Imports System.ComponentModel -Imports System.Diagnostics Imports System.Globalization +Imports System.Diagnostics +Imports System.Dynamic Imports System.Reflection +Imports System.Security Imports Microsoft.VisualBasic.CompilerServices.Symbols Imports Microsoft.VisualBasic.CompilerServices.ConversionResolution Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils Imports Microsoft.VisualBasic.CompilerServices.Utils -Imports Container = Microsoft.VisualBasic.CompilerServices.Symbols.Container -Namespace Global.Microsoft.VisualBasic.CompilerServices - - +Namespace Microsoft.VisualBasic.CompilerServices + + Public NotInheritable Class Conversions + Private Sub New() End Sub - Private Shared Function GetEnumValue(Value As Object) As Object - Dim underlyingType As Type = System.Enum.GetUnderlyingType(Value.GetType()) - If underlyingType.Equals(GetType(SByte)) Then - Return DirectCast(Value, SByte) - ElseIf underlyingType.Equals(GetType(Byte)) Then - Return DirectCast(Value, Byte) - ElseIf underlyingType.Equals(GetType(Global.System.Int16)) Then - Return DirectCast(Value, Global.System.Int16) - ElseIf underlyingType.Equals(GetType(Global.System.UInt16)) Then - Return DirectCast(Value, Global.System.UInt16) - ElseIf underlyingType.Equals(GetType(Global.System.Int32)) Then - Return DirectCast(Value, Global.System.Int32) - ElseIf underlyingType.Equals(GetType(Global.System.UInt32)) Then - Return DirectCast(Value, Global.System.UInt32) - ElseIf underlyingType.Equals(GetType(Global.System.Int64)) Then - Return DirectCast(Value, Global.System.Int64) - ElseIf underlyingType.Equals(GetType(Global.System.UInt64)) Then - Return DirectCast(Value, Global.System.UInt64) - Else - Throw New Global.System.InvalidCastException - End If - End Function - Public Shared Function ToBoolean(Value As String) As Boolean + + Public Shared Function ToBoolean(ByVal Value As String) As Boolean + If Value Is Nothing Then Value = "" End If + Try - Dim loc As Global.System.Globalization.CultureInfo = GetCultureInfo() - If loc.CompareInfo.Compare(Value, Boolean.FalseString, Global.System.Globalization.CompareOptions.IgnoreCase) = 0 Then + Dim loc As CultureInfo = GetCultureInfo() + If String.Compare(Value, Boolean.FalseString, True, loc) = 0 Then Return False - ElseIf loc.CompareInfo.Compare(Value, Boolean.TrueString, Global.System.Globalization.CompareOptions.IgnoreCase) = 0 Then + ElseIf String.Compare(Value, Boolean.TrueString, True, loc) = 0 Then Return True End If - Dim i64Value As Global.System.Int64 + + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CBool(i64Value) End If + Return CBool(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Boolean"), e) End Try + End Function - Public Shared Function ToBoolean(Value As Object) As Boolean + + Public Shared Function ToBoolean(ByVal Value As Object) As Boolean + If Value Is Nothing Then Return False End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CBool(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CBool(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CBool(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CBool(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CBool(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CBool(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CBool(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CBool(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CBool(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CBool(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CBool(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CBool(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CBool(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToByte(Value As String) As Byte + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CBool(DirectCast(Value, Boolean)) + Else + Return CBool(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CBool(DirectCast(Value, SByte)) + Else + Return CBool(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CBool(DirectCast(Value, Byte)) + Else + Return CBool(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CBool(DirectCast(Value, Int16)) + Else + Return CBool(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CBool(DirectCast(Value, UInt16)) + Else + Return CBool(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CBool(DirectCast(Value, Int32)) + Else + Return CBool(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CBool(DirectCast(Value, UInt32)) + Else + Return CBool(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CBool(DirectCast(Value, Int64)) + Else + 'Using ToInt64 also handles enums + Return CBool(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CBool(DirectCast(Value, UInt64)) + Else + Return CBool(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToBoolean(Nothing) + Else + Return CBool(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CBool(DirectCast(Value, Single)) + Else + Return CBool(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CBool(DirectCast(Value, Double)) + Else + Return CBool(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CBool(StringValue) + Else + Return CBool(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Boolean")) + End Function + + Public Shared Function ToByte(ByVal Value As String) As Byte + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CByte(i64Value) End If + Return CByte(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Byte"), e) 'UNSIGNED: make these strings constants End Try + End Function - Public Shared Function ToByte(Value As Object) As Byte + + Public Shared Function ToByte(ByVal Value As Object) As Byte + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CByte(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CByte(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CByte(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CByte(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CByte(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CByte(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CByte(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CByte(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CByte(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CByte(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CByte(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CByte(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CByte(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - - Public Shared Function ToSByte(Value As String) As SByte + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CByte(DirectCast(Value, Boolean)) + Else + Return CByte(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CByte(DirectCast(Value, SByte)) + Else + Return CByte(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CByte(DirectCast(Value, Byte)) + Else + Return CByte(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CByte(DirectCast(Value, Int16)) + Else + Return CByte(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CByte(DirectCast(Value, UInt16)) + Else + Return CByte(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CByte(DirectCast(Value, Int32)) + Else + Return CByte(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CByte(DirectCast(Value, UInt32)) + Else + Return CByte(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CByte(DirectCast(Value, Int64)) + Else + Return CByte(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CByte(DirectCast(Value, UInt64)) + Else + Return CByte(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToByte(Nothing) + Else + Return CByte(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CByte(DirectCast(Value, Single)) + Else + Return CByte(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CByte(DirectCast(Value, Double)) + Else + Return CByte(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + If StringValue IsNot Nothing Then + Return CByte(StringValue) + Else + Return CByte(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Byte")) + + End Function + + + Public Shared Function ToSByte(ByVal Value As String) As SByte + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CSByte(i64Value) End If + Return CSByte(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "SByte"), e) End Try + End Function - - Public Shared Function ToSByte(Value As Object) As SByte + + + Public Shared Function ToSByte(ByVal Value As Object) As SByte + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CSByte(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CSByte(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CSByte(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CSByte(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CSByte(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CSByte(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CSByte(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CSByte(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CSByte(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CSByte(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CSByte(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CSByte(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CSByte(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToShort(Value As String) As Short + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface Is Nothing Then + GoTo ThrowInvalidCast + End If + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CSByte(DirectCast(Value, Boolean)) + Else + Return CSByte(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CSByte(DirectCast(Value, SByte)) + Else + Return CSByte(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CSByte(DirectCast(Value, Byte)) + Else + Return CSByte(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CSByte(DirectCast(Value, Int16)) + Else + Return CSByte(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CSByte(DirectCast(Value, UInt16)) + Else + Return CSByte(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CSByte(DirectCast(Value, Int32)) + Else + Return CSByte(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CSByte(DirectCast(Value, UInt32)) + Else + Return CSByte(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CSByte(DirectCast(Value, Int64)) + Else + Return CSByte(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CSByte(DirectCast(Value, UInt64)) + Else + Return CSByte(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToSByte(Nothing) + Else + Return CSByte(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CSByte(DirectCast(Value, Single)) + Else + Return CSByte(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CSByte(DirectCast(Value, Double)) + Else + Return CSByte(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CSByte(StringValue) + Else + Return CSByte(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + +ThrowInvalidCast: + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "SByte")) + + End Function + + Public Shared Function ToShort(ByVal Value As String) As Short + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CShort(i64Value) End If + Return CShort(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Short"), e) End Try + End Function - Public Shared Function ToShort(Value As Object) As Short + + Public Shared Function ToShort(ByVal Value As Object) As Short + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CShort(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CShort(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CShort(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CShort(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CShort(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CShort(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CShort(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CShort(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CShort(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CShort(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CShort(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CShort(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CShort(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - - Public Shared Function ToUShort(Value As String) As UShort + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CShort(DirectCast(Value, Boolean)) + Else + Return CShort(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CShort(DirectCast(Value, SByte)) + Else + Return CShort(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CShort(DirectCast(Value, Byte)) + Else + Return CShort(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CShort(DirectCast(Value, Int16)) + Else + Return CShort(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CShort(DirectCast(Value, UInt16)) + Else + Return CShort(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CShort(DirectCast(Value, Int32)) + Else + Return CShort(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CShort(DirectCast(Value, UInt32)) + Else + Return CShort(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CShort(DirectCast(Value, Int64)) + Else + Return CShort(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CShort(DirectCast(Value, UInt64)) + Else + Return CShort(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToInt16(Nothing) + Else + Return CShort(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CShort(DirectCast(Value, Single)) + Else + Return CShort(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CShort(DirectCast(Value, Double)) + Else + Return CShort(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CShort(StringValue) + Else + Return CShort(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Short")) + + End Function + + + Public Shared Function ToUShort(ByVal Value As String) As UShort + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CUShort(i64Value) End If + Return CUShort(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "UShort"), e) End Try + End Function - - Public Shared Function ToUShort(Value As Object) As UShort + + + Public Shared Function ToUShort(ByVal Value As Object) As UShort + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CUShort(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CUShort(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CUShort(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CUShort(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CUShort(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CUShort(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CUShort(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CUShort(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CUShort(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CUShort(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CUShort(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CUShort(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CUShort(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToInteger(Value As String) As Integer + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CUShort(DirectCast(Value, Boolean)) + Else + Return CUShort(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CUShort(DirectCast(Value, SByte)) + Else + Return CUShort(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CUShort(DirectCast(Value, Byte)) + Else + Return CUShort(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CUShort(DirectCast(Value, Int16)) + Else + Return CUShort(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CUShort(DirectCast(Value, UInt16)) + Else + Return CUShort(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CUShort(DirectCast(Value, Int32)) + Else + Return CUShort(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CUShort(DirectCast(Value, UInt32)) + Else + Return CUShort(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CUShort(DirectCast(Value, Int64)) + Else + Return CUShort(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CUShort(DirectCast(Value, UInt64)) + Else + Return CUShort(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToUInt16(Nothing) + Else + Return CUShort(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CUShort(DirectCast(Value, Single)) + Else + Return CUShort(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CUShort(DirectCast(Value, Double)) + Else + Return CUShort(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CUShort(StringValue) + Else + Return CUShort(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "UShort")) + End Function + + Public Shared Function ToInteger(ByVal Value As String) As Integer + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CInt(i64Value) End If + Return CInt(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Integer"), e) End Try + End Function - Public Shared Function ToInteger(Value As Object) As Integer + + Public Shared Function ToInteger(ByVal Value As Object) As Integer + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CInt(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CInt(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CInt(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CInt(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CInt(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CInt(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CInt(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CInt(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CInt(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CInt(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CInt(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CInt(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CInt(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - - Public Shared Function ToUInteger(Value As String) As UInteger + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CInt(DirectCast(Value, Boolean)) + Else + Return CInt(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CInt(DirectCast(Value, SByte)) + Else + Return CInt(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CInt(DirectCast(Value, Byte)) + Else + Return CInt(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CInt(DirectCast(Value, Int16)) + Else + Return CInt(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CInt(DirectCast(Value, UInt16)) + Else + Return CInt(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CInt(DirectCast(Value, Int32)) + Else + Return CInt(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CInt(DirectCast(Value, UInt32)) + Else + Return CInt(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CInt(DirectCast(Value, Int64)) + Else + Return CInt(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CInt(DirectCast(Value, UInt64)) + Else + Return CInt(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToInt32(Nothing) + Else + Return CInt(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CInt(DirectCast(Value, Single)) + Else + Return CInt(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CInt(DirectCast(Value, Double)) + Else + Return CInt(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CInt(StringValue) + Else + Return CInt(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Integer")) + End Function + + + Public Shared Function ToUInteger(ByVal Value As String) As UInteger + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CUInt(i64Value) End If + Return CUInt(ParseDouble(Value)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "UInteger"), e) End Try + End Function - - Public Shared Function ToUInteger(Value As Object) As UInteger + + + Public Shared Function ToUInteger(ByVal Value As Object) As UInteger + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CUInt(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CUInt(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CUInt(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CUInt(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CUInt(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CUInt(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CUInt(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CUInt(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CUInt(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CUInt(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CUInt(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CUInt(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CUInt(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToLong(Value As String) As Long - If (Value Is Nothing) Then + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CUInt(DirectCast(Value, Boolean)) + Else + Return CUInt(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CUInt(DirectCast(Value, SByte)) + Else + Return CUInt(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CUInt(DirectCast(Value, Byte)) + Else + Return CUInt(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CUInt(DirectCast(Value, Int16)) + Else + Return CUInt(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CUInt(DirectCast(Value, UInt16)) + Else + Return CUInt(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CUInt(DirectCast(Value, Int32)) + Else + Return CUInt(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CUInt(DirectCast(Value, UInt32)) + Else + Return CUInt(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CUInt(DirectCast(Value, Int64)) + Else + Return CUInt(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CUInt(DirectCast(Value, UInt64)) + Else + Return CUInt(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToUInt32(Nothing) + Else + Return CUInt(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CUInt(DirectCast(Value, Single)) + Else + Return CUInt(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CUInt(DirectCast(Value, Double)) + Else + Return CUInt(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CUInt(StringValue) + Else + Return CUInt(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "UInteger")) + + End Function + + Public Shared Function ToLong(ByVal Value As String) As Long + + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CLng(i64Value) End If + + 'Using Decimal parse so that we full range of Int64 + ' and still get currency and thousands parsing Return CLng(ParseDecimal(Value, Nothing)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Long"), e) End Try + End Function - Public Shared Function ToLong(Value As Object) As Long + + Public Shared Function ToLong(ByVal Value As Object) As Long + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CLng(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CLng(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CLng(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CLng(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CLng(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CLng(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CLng(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CLng(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CLng(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CLng(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CLng(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CLng(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CLng(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - - Public Shared Function ToULong(Value As String) As ULong - If (Value Is Nothing) Then + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CLng(DirectCast(Value, Boolean)) + Else + Return CLng(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CLng(DirectCast(Value, SByte)) + Else + Return CLng(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CLng(DirectCast(Value, Byte)) + Else + Return CLng(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CLng(DirectCast(Value, Int16)) + Else + Return CLng(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CLng(DirectCast(Value, UInt16)) + Else + Return CLng(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CLng(DirectCast(Value, Int32)) + Else + Return CLng(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CLng(DirectCast(Value, UInt32)) + Else + Return CLng(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CLng(DirectCast(Value, Int64)) + Else + Return CLng(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CLng(DirectCast(Value, UInt64)) + Else + Return CLng(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToInt64(Nothing) + Else + Return CLng(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CLng(DirectCast(Value, Single)) + Else + Return CLng(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CLng(DirectCast(Value, Double)) + Else + Return CLng(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CLng(StringValue) + Else + Return CLng(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Long")) + End Function + + + Public Shared Function ToULong(ByVal Value As String) As ULong + + If Value Is Nothing Then Return 0 End If + Try - Dim ui64Value As Global.System.UInt64 + Dim ui64Value As UInt64 + If IsHexOrOctValue(Value, ui64Value) Then Return CULng(ui64Value) End If + + 'Using Decimal parse so that we full range of Int64 + ' and still get currency and thousands parsing Return CULng(ParseDecimal(Value, Nothing)) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "ULong"), e) End Try + End Function - - Public Shared Function ToULong(Value As Object) As ULong + + + Public Shared Function ToULong(ByVal Value As Object) As ULong + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CULng(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CULng(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CULng(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CULng(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CULng(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CULng(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CULng(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CULng(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CULng(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CULng(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CULng(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CULng(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CULng(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToDecimal(Value As Boolean) As Decimal + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CULng(DirectCast(Value, Boolean)) + Else + Return CULng(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CULng(DirectCast(Value, SByte)) + Else + Return CULng(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CULng(DirectCast(Value, Byte)) + Else + Return CULng(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CULng(DirectCast(Value, Int16)) + Else + Return CULng(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CULng(DirectCast(Value, UInt16)) + Else + Return CULng(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CULng(DirectCast(Value, Int32)) + Else + Return CULng(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CULng(DirectCast(Value, UInt32)) + Else + Return CULng(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CULng(DirectCast(Value, Int64)) + Else + Return CULng(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CULng(DirectCast(Value, UInt64)) + Else + Return CULng(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToUInt64(Nothing) + Else + Return CULng(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CULng(DirectCast(Value, Single)) + Else + Return CULng(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CULng(DirectCast(Value, Double)) + Else + Return CULng(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CULng(StringValue) + Else + Return CULng(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "ULong")) + End Function + + Public Shared Function ToDecimal(ByVal Value As Boolean) As Decimal If Value Then Return -1D Else Return 0D End If End Function - Public Shared Function ToDecimal(Value As String) As Decimal + + Public Shared Function ToDecimal(ByVal Value As String) As Decimal + Return ToDecimal(Value, Nothing) + End Function + + Friend Shared Function ToDecimal(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Decimal If Value Is Nothing Then Return 0D End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CDec(i64Value) End If - Return ParseDecimal(Value, Nothing) - Catch e1 As Global.System.OverflowException - Throw e1 - Catch e2 As Global.System.FormatException - Throw New Global.System.InvalidCastException(e2.Message, e2) + + Return ParseDecimal(Value, NumberFormat) + + Catch e1 As OverflowException + Throw VbMakeException(vbErrors.Overflow) + Catch e2 As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Decimal")) End Try End Function - Public Shared Function ToDecimal(Value As Object) As Decimal + + Public Shared Function ToDecimal(ByVal Value As Object) As Decimal + Return ToDecimal(Value, Nothing) + End Function + + Friend Shared Function ToDecimal(ByVal Value As Object, ByVal NumberFormat As NumberFormatInfo) As Decimal + If Value Is Nothing Then Return 0D End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CDec(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CDec(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CDec(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CDec(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CDec(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CDec(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CDec(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CDec(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CDec(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CDec(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CDec(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CDec(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CDec(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Private Shared Function ParseDecimal(value As String, numberFormat As Global.System.Globalization.NumberFormatInfo) As Decimal - Dim normalizedNumberFormat As Global.System.Globalization.NumberFormatInfo - Dim culture As Global.System.Globalization.CultureInfo = GetCultureInfo() - If numberFormat Is Nothing Then - numberFormat = culture.NumberFormat - End If - normalizedNumberFormat = GetNormalizedNumberFormat(numberFormat) - Const flags As Global.System.Globalization.NumberStyles = - Global.System.Globalization.NumberStyles.AllowDecimalPoint Or - Global.System.Globalization.NumberStyles.AllowExponent Or - Global.System.Globalization.NumberStyles.AllowLeadingSign Or - Global.System.Globalization.NumberStyles.AllowLeadingWhite Or - Global.System.Globalization.NumberStyles.AllowThousands Or - Global.System.Globalization.NumberStyles.AllowTrailingSign Or - Global.System.Globalization.NumberStyles.AllowParentheses Or - Global.System.Globalization.NumberStyles.AllowTrailingWhite Or - Global.System.Globalization.NumberStyles.AllowCurrencySymbol - value = ToHalfwidthNumbers(value, culture) + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CDec(DirectCast(Value, Boolean)) + Else + Return CDec(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CDec(DirectCast(Value, SByte)) + Else + Return CDec(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CDec(DirectCast(Value, Byte)) + Else + Return CDec(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CDec(DirectCast(Value, Int16)) + Else + Return CDec(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CDec(DirectCast(Value, UInt16)) + Else + Return CDec(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CDec(DirectCast(Value, Int32)) + Else + Return CDec(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CDec(DirectCast(Value, UInt32)) + Else + Return CDec(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CDec(DirectCast(Value, Int64)) + Else + Return CDec(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CDec(DirectCast(Value, UInt64)) + Else + Return CDec(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + Return ValueInterface.ToDecimal(Nothing) + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CDec(DirectCast(Value, Single)) + Else + Return CDec(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CDec(DirectCast(Value, Double)) + Else + Return CDec(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Return ToDecimal(ValueInterface.ToString(Nothing), NumberFormat) + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Decimal")) + End Function + + Private Shared Function ParseDecimal(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Decimal + Dim NormalizedNumberFormat As NumberFormatInfo + Dim culture As CultureInfo = GetCultureInfo() + + If NumberFormat Is Nothing Then + NumberFormat = culture.NumberFormat + End If + + ' Normalize number format settings to enable us to first use the numeric settings for both currency and number parsing + ' compatible with VB6 + NormalizedNumberFormat = GetNormalizedNumberFormat(NumberFormat) + + Const flags As NumberStyles = + NumberStyles.AllowDecimalPoint Or + NumberStyles.AllowExponent Or + NumberStyles.AllowLeadingSign Or + NumberStyles.AllowLeadingWhite Or + NumberStyles.AllowThousands Or + NumberStyles.AllowTrailingSign Or + NumberStyles.AllowParentheses Or + NumberStyles.AllowTrailingWhite Or + NumberStyles.AllowCurrencySymbol + + Value = ToHalfwidthNumbers(Value, culture) + Try - Return Global.System.Decimal.Parse(value, flags, normalizedNumberFormat) - Catch formatEx As Global.System.FormatException When Not (numberFormat Is normalizedNumberFormat) - Return Global.System.Decimal.Parse(value, flags, numberFormat) - Catch ex As Global.System.Exception - Throw ex + ' Use numeric settings to parse + Return Decimal.Parse(Value, flags, NormalizedNumberFormat) + Catch FormatEx As FormatException When Not (NumberFormat Is NormalizedNumberFormat) + ' Use currency settings to parse + Return Decimal.Parse(Value, flags, NumberFormat) + Catch Ex As Exception + Throw Ex End Try + End Function - Private Shared Function GetNormalizedNumberFormat(inNumberFormat As Global.System.Globalization.NumberFormatInfo) As Global.System.Globalization.NumberFormatInfo - Dim outNumberFormat As Global.System.Globalization.NumberFormatInfo - With inNumberFormat + + Private Shared Function GetNormalizedNumberFormat(ByVal InNumberFormat As NumberFormatInfo) As NumberFormatInfo + ' This method returns a NumberFormat with the relevant Currency Settings to be the same as the Number Settings + ' In - NumberFormat to be normalized - this is not changed by this Method + ' Return - Normalized NumberFormat + + Dim OutNumberFormat As NumberFormatInfo + + With InNumberFormat If (Not .CurrencyDecimalSeparator Is Nothing) AndAlso (Not .NumberDecimalSeparator Is Nothing) AndAlso (Not .CurrencyGroupSeparator Is Nothing) AndAlso @@ -605,202 +1539,380 @@ Namespace Global.Microsoft.VisualBasic.CompilerServices (.CurrencyDecimalSeparator.Chars(0) = .NumberDecimalSeparator.Chars(0)) AndAlso (.CurrencyGroupSeparator.Chars(0) = .NumberGroupSeparator.Chars(0)) AndAlso (.CurrencyDecimalDigits = .NumberDecimalDigits) Then - Return inNumberFormat + Return InNumberFormat End If End With - With inNumberFormat + + With InNumberFormat If (Not .CurrencyDecimalSeparator Is Nothing) AndAlso (Not .NumberDecimalSeparator Is Nothing) AndAlso (.CurrencyDecimalSeparator.Length = .NumberDecimalSeparator.Length) AndAlso (Not .CurrencyGroupSeparator Is Nothing) AndAlso (Not .NumberGroupSeparator Is Nothing) AndAlso (.CurrencyGroupSeparator.Length = .NumberGroupSeparator.Length) Then + Dim i As Integer For i = 0 To .CurrencyDecimalSeparator.Length - 1 If (.CurrencyDecimalSeparator.Chars(i) <> .NumberDecimalSeparator.Chars(i)) Then GoTo MisMatch Next + For i = 0 To .CurrencyGroupSeparator.Length - 1 If (.CurrencyGroupSeparator.Chars(i) <> .NumberGroupSeparator.Chars(i)) Then GoTo MisMatch Next - Return inNumberFormat + + Return InNumberFormat End If End With + MisMatch: - outNumberFormat = DirectCast(inNumberFormat.Clone, Global.System.Globalization.NumberFormatInfo) - With outNumberFormat + + OutNumberFormat = DirectCast(InNumberFormat.Clone, NumberFormatInfo) + + ' Set the Currency Settings to be the Same as the Numeric Settings + With OutNumberFormat .CurrencyDecimalSeparator = .NumberDecimalSeparator .CurrencyGroupSeparator = .NumberGroupSeparator .CurrencyDecimalDigits = .NumberDecimalDigits End With - Return outNumberFormat + + Return OutNumberFormat + End Function + + Public Shared Function ToSingle(ByVal Value As String) As Single + Return ToSingle(Value, Nothing) + End Function + + Friend Shared Function ToSingle(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Single + + If Value Is Nothing Then + Return 0 + End If + + Try + Dim i64Value As Int64 + + If IsHexOrOctValue(Value, i64Value) Then + Return CSng(i64Value) + End If + + Dim Result As Double = ParseDouble(Value, NumberFormat) + If (Result < Single.MinValue OrElse Result > Single.MaxValue) AndAlso + Not Double.IsInfinity(Result) Then + Throw New OverflowException + End If + Return CSng(Result) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Single"), e) + End Try + + End Function + + Public Shared Function ToSingle(ByVal Value As Object) As Single + Return ToSingle(Value, Nothing) End Function - Public Shared Function ToSingle(Value As String) As Single + + Friend Shared Function ToSingle(ByVal Value As Object, ByVal NumberFormat As NumberFormatInfo) As Single + If Value Is Nothing Then Return 0 End If - Try - Dim i64Value As Global.System.Int64 - If IsHexOrOctValue(Value, i64Value) Then - Return CSng(i64Value) - End If - Dim result As Double = ParseDouble(Value) - If (result < Global.System.Single.MinValue OrElse result > Global.System.Single.MaxValue) AndAlso - Not Global.System.Double.IsInfinity(result) Then - Throw New Global.System.OverflowException - End If - Return CSng(result) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) - End Try + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CSng(DirectCast(Value, Boolean)) + Else + Return CSng(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CSng(DirectCast(Value, SByte)) + Else + Return CSng(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CSng(DirectCast(Value, Byte)) + Else + Return CSng(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CSng(DirectCast(Value, Int16)) + Else + Return CSng(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CSng(DirectCast(Value, UInt16)) + Else + Return CSng(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CSng(DirectCast(Value, Int32)) + Else + Return CSng(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CSng(DirectCast(Value, UInt32)) + Else + Return CSng(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CSng(DirectCast(Value, Int64)) + Else + Return CSng(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CSng(DirectCast(Value, UInt64)) + Else + Return CSng(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToSingle(Nothing) + Else + Return CSng(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return DirectCast(Value, Single) + Else + Return ValueInterface.ToSingle(Nothing) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CSng(DirectCast(Value, Double)) + Else + Return CSng(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Return ToSingle(ValueInterface.ToString(Nothing), NumberFormat) + + Case Else + ' Fall through to error + End Select + + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Single")) End Function - Public Shared Function ToSingle(Value As Object) As Single - If Value Is Nothing Then - Return 0 - End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CSng(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CSng(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CSng(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CSng(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CSng(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CSng(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CSng(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CSng(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CSng(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CSng(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CSng(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CSng(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CSng(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Public Shared Function ToDouble(Value As String) As Double + + Public Shared Function ToDouble(ByVal Value As String) As Double + Return ToDouble(Value, Nothing) + End Function + + Friend Shared Function ToDouble(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Double + If Value Is Nothing Then Return 0 End If + Try - Dim i64Value As Global.System.Int64 + Dim i64Value As Int64 + If IsHexOrOctValue(Value, i64Value) Then Return CDbl(i64Value) End If - Return ParseDouble(Value) - Catch e As Global.System.FormatException - Throw New Global.System.InvalidCastException(e.Message, e) + Return ParseDouble(Value, NumberFormat) + + Catch e As FormatException + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Double"), e) End Try + + End Function + + Public Shared Function ToDouble(ByVal Value As Object) As Double + Return ToDouble(Value, Nothing) End Function - Public Shared Function ToDouble(Value As Object) As Double + + Friend Shared Function ToDouble(ByVal Value As Object, ByVal NumberFormat As NumberFormatInfo) As Double + If Value Is Nothing Then Return 0 End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CDbl(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CDbl(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CDbl(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CDbl(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CDbl(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CDbl(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CDbl(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CDbl(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CDbl(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CDbl(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CDbl(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CDbl(DirectCast(Value, Double)) - ElseIf TypeOf Value Is String Then - Return CDbl(DirectCast(Value, String)) - End If - Throw New Global.System.InvalidCastException() - End Function - Private Shared Function ParseDouble(value As String) As Double - Dim normalizedNumberFormat As Global.System.Globalization.NumberFormatInfo - Dim culture As Global.System.Globalization.CultureInfo = GetCultureInfo() - Dim numberFormat As Global.System.Globalization.NumberFormatInfo = culture.NumberFormat - normalizedNumberFormat = GetNormalizedNumberFormat(numberFormat) - Const flags As Global.System.Globalization.NumberStyles = - Global.System.Globalization.NumberStyles.AllowDecimalPoint Or - Global.System.Globalization.NumberStyles.AllowExponent Or - Global.System.Globalization.NumberStyles.AllowLeadingSign Or - Global.System.Globalization.NumberStyles.AllowLeadingWhite Or - Global.System.Globalization.NumberStyles.AllowThousands Or - Global.System.Globalization.NumberStyles.AllowTrailingSign Or - Global.System.Globalization.NumberStyles.AllowParentheses Or - Global.System.Globalization.NumberStyles.AllowTrailingWhite Or - Global.System.Globalization.NumberStyles.AllowCurrencySymbol - value = ToHalfwidthNumbers(value, culture) - Try - Return Global.System.Double.Parse(value, flags, normalizedNumberFormat) - Catch formatEx As Global.System.FormatException When Not (numberFormat Is normalizedNumberFormat) - Return Global.System.Double.Parse(value, flags, numberFormat) - Catch ex As Global.System.Exception - Throw ex - End Try + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + + Case TypeCode.Boolean + If TypeOf Value Is Boolean Then + Return CDbl(DirectCast(Value, Boolean)) + Else + Return CDbl(ValueInterface.ToBoolean(Nothing)) + End If + + Case TypeCode.SByte + If TypeOf Value Is SByte Then + Return CDbl(DirectCast(Value, SByte)) + Else + Return CDbl(ValueInterface.ToSByte(Nothing)) + End If + + Case TypeCode.Byte + If TypeOf Value Is Byte Then + Return CDbl(DirectCast(Value, Byte)) + Else + Return CDbl(ValueInterface.ToByte(Nothing)) + End If + + Case TypeCode.Int16 + If TypeOf Value Is Int16 Then + Return CDbl(DirectCast(Value, Int16)) + Else + Return CDbl(ValueInterface.ToInt16(Nothing)) + End If + + Case TypeCode.UInt16 + If TypeOf Value Is UInt16 Then + Return CDbl(DirectCast(Value, UInt16)) + Else + Return CDbl(ValueInterface.ToUInt16(Nothing)) + End If + + Case TypeCode.Int32 + If TypeOf Value Is Int32 Then + Return CDbl(DirectCast(Value, Int32)) + Else + Return CDbl(ValueInterface.ToInt32(Nothing)) + End If + + Case TypeCode.UInt32 + If TypeOf Value Is UInt32 Then + Return CDbl(DirectCast(Value, UInt32)) + Else + Return CDbl(ValueInterface.ToUInt32(Nothing)) + End If + + Case TypeCode.Int64 + If TypeOf Value Is Int64 Then + Return CDbl(DirectCast(Value, Int64)) + Else + Return CDbl(ValueInterface.ToInt64(Nothing)) + End If + + Case TypeCode.UInt64 + If TypeOf Value Is UInt64 Then + Return CDbl(DirectCast(Value, UInt64)) + Else + Return CDbl(ValueInterface.ToUInt64(Nothing)) + End If + + Case TypeCode.Decimal + If TypeOf Value Is Decimal Then + Return ValueInterface.ToDouble(Nothing) + Else + Return CDbl(ValueInterface.ToDecimal(Nothing)) + End If + + Case TypeCode.Single + If TypeOf Value Is Single Then + Return CDbl(DirectCast(Value, Single)) + Else + Return CDbl(ValueInterface.ToSingle(Nothing)) + End If + + Case TypeCode.Double + If TypeOf Value Is Double Then + Return CDbl(DirectCast(Value, Double)) + Else + Return CDbl(ValueInterface.ToDouble(Nothing)) + End If + + Case TypeCode.DateTime, + TypeCode.Char + ' Fall through to error + + Case TypeCode.String + Return ToDouble(ValueInterface.ToString(Nothing), NumberFormat) + + Case Else + ' Fall through to error + End Select + End If + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Double")) + + End Function + + Private Shared Function ParseDouble(ByVal Value As String) As Double + Return ParseDouble(Value, Nothing) End Function Friend Shared Function TryParseDouble(ByVal Value As String, ByRef Result As Double) As Boolean - Dim numberFormat As NumberFormatInfo - Dim normalizedNumberFormat As NumberFormatInfo + Dim NumberFormat As NumberFormatInfo + Dim NormalizedNumberFormat As NumberFormatInfo Dim culture As CultureInfo = GetCultureInfo() - numberFormat = culture.NumberFormat - normalizedNumberFormat = GetNormalizedNumberFormat(numberFormat) + NumberFormat = culture.NumberFormat + NormalizedNumberFormat = GetNormalizedNumberFormat(NumberFormat) Const flags As NumberStyles = - NumberStyles.AllowDecimalPoint Or - NumberStyles.AllowExponent Or - NumberStyles.AllowLeadingSign Or - NumberStyles.AllowLeadingWhite Or - NumberStyles.AllowThousands Or - NumberStyles.AllowTrailingSign Or - NumberStyles.AllowParentheses Or - NumberStyles.AllowTrailingWhite Or - NumberStyles.AllowCurrencySymbol + NumberStyles.AllowDecimalPoint Or + NumberStyles.AllowExponent Or + NumberStyles.AllowLeadingSign Or + NumberStyles.AllowLeadingWhite Or + NumberStyles.AllowThousands Or + NumberStyles.AllowTrailingSign Or + NumberStyles.AllowParentheses Or + NumberStyles.AllowTrailingWhite Or + NumberStyles.AllowCurrencySymbol Value = ToHalfwidthNumbers(Value, culture) ' The below code handles the 80% case efficiently and is inefficient only when the numeric and currency settings ' are different - - If numberFormat Is normalizedNumberFormat Then - Return System.Double.TryParse(Value, flags, normalizedNumberFormat, Result) + If NumberFormat Is NormalizedNumberFormat Then + Return Double.TryParse(Value, flags, NormalizedNumberFormat, Result) Else Try ' Use numeric settings to parse ' Note that we use Parse instead of TryParse in order to distinguish whether the conversion failed ' due to FormatException or other exception like OverFlowException, etc. - Result = System.Double.Parse(Value, flags, normalizedNumberFormat) + Result = Double.Parse(Value, flags, NormalizedNumberFormat) Return True Catch FormatEx As FormatException ' Use currency settings to parse Try - Return System.Double.TryParse(Value, flags, numberFormat, Result) + Return Double.TryParse(Value, flags, NumberFormat, Result) Catch ex As ArgumentException Return False End Try @@ -808,7 +1920,7 @@ MisMatch: Throw ex Catch ex As OutOfMemoryException Throw ex - Catch ex As System.Threading.ThreadAbortException + Catch ex As Threading.ThreadAbortException Throw ex Catch Ex As Exception Return False @@ -817,487 +1929,647 @@ MisMatch: End Function - Public Shared Function ToDate(Value As String) As Date - Dim parsedDate As Global.System.DateTime - Const parseStyle As Global.System.Globalization.DateTimeStyles = - Global.System.Globalization.DateTimeStyles.AllowWhiteSpaces Or - Global.System.Globalization.DateTimeStyles.NoCurrentDateDefault - Dim culture As Global.System.Globalization.CultureInfo = GetCultureInfo() - Dim result As Boolean = Global.System.DateTime.TryParse(ToHalfwidthNumbers(Value, culture), culture, parseStyle, parsedDate) - If result Then - Return parsedDate + Private Shared Function ParseDouble(ByVal Value As String, ByVal NumberFormat As NumberFormatInfo) As Double + Dim NormalizedNumberFormat As NumberFormatInfo + Dim culture As CultureInfo = GetCultureInfo() + + If NumberFormat Is Nothing Then + NumberFormat = culture.NumberFormat + End If + + ' Normalize number format settings to enable us to first use the numeric settings for both currency and number parsing + ' compatible with VB6 + NormalizedNumberFormat = GetNormalizedNumberFormat(NumberFormat) + Const flags As NumberStyles = + NumberStyles.AllowDecimalPoint Or + NumberStyles.AllowExponent Or + NumberStyles.AllowLeadingSign Or + NumberStyles.AllowLeadingWhite Or + NumberStyles.AllowThousands Or + NumberStyles.AllowTrailingSign Or + NumberStyles.AllowParentheses Or + NumberStyles.AllowTrailingWhite Or + NumberStyles.AllowCurrencySymbol + Value = ToHalfwidthNumbers(Value, culture) + + Try + ' Use numeric settings to parse + Return Double.Parse(Value, flags, NormalizedNumberFormat) + Catch FormatEx As FormatException When Not (NumberFormat Is NormalizedNumberFormat) + ' Use currency settings to parse + Return Double.Parse(Value, flags, NumberFormat) + Catch Ex As Exception + Throw Ex + End Try + + End Function + + Public Shared Function ToDate(ByVal Value As String) As Date + Dim ParsedDate As DateTime + + If TryParseDate(Value, ParsedDate) Then + Return ParsedDate Else - Throw New Global.System.InvalidCastException() + 'Truncate the string to 32 characters for the message + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromStringTo, Left(Value, 32), "Date")) End If End Function - Public Shared Function ToDate(Value As Object) As Date + + Public Shared Function ToDate(ByVal Value As Object) As Date + If Value Is Nothing Then Return Nothing End If - If TypeOf Value Is Global.System.DateTime Then - Return CDate(DirectCast(Value, Global.System.DateTime)) - ElseIf TypeOf Value Is String Then - Return CDate(DirectCast(Value, String)) + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + Case TypeCode.Boolean, + TypeCode.SByte, + TypeCode.Byte, + TypeCode.Int16, + TypeCode.UInt16, + TypeCode.Int32, + TypeCode.UInt32, + TypeCode.Int64, + TypeCode.UInt64, + TypeCode.Decimal, + TypeCode.Single, + TypeCode.Double, + TypeCode.Char + ' Fall through to error + + Case TypeCode.DateTime + If TypeOf Value Is DateTime Then + Return CDate(DirectCast(Value, DateTime)) + Else + Return CDate(ValueInterface.ToDateTime(Nothing)) + End If + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CDate(StringValue) + Else + Return CDate(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select + End If - Throw New Global.System.InvalidCastException() + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Date")) End Function - Friend Shared Function TryParseDate(ByVal Value As String, ByRef Result As System.DateTime) As Boolean + Friend Shared Function TryParseDate(ByVal Value As String, ByRef Result As DateTime) As Boolean Const ParseStyle As DateTimeStyles = - DateTimeStyles.AllowWhiteSpaces Or - DateTimeStyles.NoCurrentDateDefault + DateTimeStyles.AllowWhiteSpaces Or + DateTimeStyles.NoCurrentDateDefault Dim Culture As CultureInfo = GetCultureInfo() - Return System.DateTime.TryParse(ToHalfwidthNumbers(Value, Culture), Culture, ParseStyle, Result) + Return DateTime.TryParse(ToHalfwidthNumbers(Value, Culture), Culture, ParseStyle, Result) End Function - Public Shared Function ToChar(Value As String) As Char + Public Shared Function ToChar(ByVal Value As String) As Char If (Value Is Nothing) OrElse (Value.Length = 0) Then - Return Global.System.Convert.ToChar(0 And &HFFFFI) + Return ControlChars.NullChar End If + Return Value.Chars(0) End Function - Public Shared Function ToChar(Value As Object) As Char + + Public Shared Function ToChar(ByVal Value As Object) As Char + If Value Is Nothing Then - Return Global.System.Convert.ToChar(0 And &HFFFFI) - End If - If TypeOf Value Is Char Then - Return CChar(DirectCast(Value, Char)) - ElseIf TypeOf Value Is String Then - Return CChar(DirectCast(Value, String)) + Return ControlChars.NullChar + End If + + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode + + ValueInterface = TryCast(Value, IConvertible) + + If ValueInterface IsNot Nothing Then + + ValueTypeCode = ValueInterface.GetTypeCode() + + Select Case ValueTypeCode + Case TypeCode.Boolean, + TypeCode.SByte, + TypeCode.Byte, + TypeCode.Int16, + TypeCode.UInt16, + TypeCode.Int32, + TypeCode.UInt32, + TypeCode.Int64, + TypeCode.UInt64, + TypeCode.Decimal, + TypeCode.Single, + TypeCode.Double, + TypeCode.DateTime + ' Fall through to error + + Case TypeCode.Char + If TypeOf Value Is Char Then + Return CChar(DirectCast(Value, Char)) + Else + Return ValueInterface.ToChar(Nothing) + End If + + Case TypeCode.String + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return CChar(StringValue) + Else + Return CChar(ValueInterface.ToString(Nothing)) + End If + + Case Else + ' Fall through to error + End Select End If - Throw New Global.System.InvalidCastException() + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Char")) End Function - Public Shared Function ToCharArrayRankOne(Value As String) As Char() + + Public Shared Function ToCharArrayRankOne(ByVal Value As String) As Char() + If Value Is Nothing Then + Value = "" + End If + Return Value.ToCharArray() + End Function - Public Shared Function ToCharArrayRankOne(Value As Object) As Char() + + Public Shared Function ToCharArrayRankOne(ByVal Value As Object) As Char() + If Value Is Nothing Then + Return "".ToCharArray() + + End If + + Dim ArrayValue As Char() = TryCast(Value, Char()) + + If ArrayValue IsNot Nothing AndAlso ArrayValue.Rank = 1 Then + + Return ArrayValue + + Else + Dim ValueInterface As IConvertible + + ValueInterface = TryCast(Value, IConvertible) + + If Not ValueInterface Is Nothing Then + + If (ValueInterface.GetTypeCode() = TypeCode.String) Then + Return ValueInterface.ToString(Nothing).ToCharArray() + End If + + End If + End If - Dim arrayValue As Char() = TryCast(Value, Char()) - If arrayValue IsNot Nothing AndAlso arrayValue.Rank = 1 Then - Return arrayValue - ElseIf TypeOf Value Is String Then - Return DirectCast(Value, String).ToCharArray() + + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "Char()")) + + End Function + + Public Shared Shadows Function ToString(ByVal Value As Boolean) As String + If Value Then + Return Boolean.TrueString + Else + Return Boolean.FalseString End If - Throw New Global.System.InvalidCastException() End Function - Public Shared Shadows Function ToString(Value As Short) As String - Return Value.ToString() + + Public Shared Shadows Function ToString(ByVal Value As Byte) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Integer) As String + + Public Shared Shadows Function ToString(ByVal Value As Char) As String Return Value.ToString() End Function - - Public Shared Shadows Function ToString(Value As UInteger) As String - Return Value.ToString() + + Public Shared Function FromCharArray(ByVal Value() As Char) As String + Return New String(Value) End Function - Public Shared Shadows Function ToString(Value As Long) As String - Return Value.ToString() + + Public Shared Function FromCharAndCount(ByVal Value As Char, ByVal Count As Integer) As String + Return New String(Value, Count) End Function - - Public Shared Shadows Function ToString(Value As ULong) As String - Return Value.ToString() + + Public Shared Function FromCharArraySubset(ByVal Value() As Char, ByVal StartIndex As Integer, ByVal Length As Integer) As String + Return New String(Value, StartIndex, Length) End Function - Public Shared Shadows Function ToString(Value As Single) As String - Return Value.ToString() + + Public Shared Shadows Function ToString(ByVal Value As Short) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Double) As String - Return Value.ToString("G") + + Public Shared Shadows Function ToString(ByVal Value As Integer) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Date) As String - Dim timeTicks As Long = Value.TimeOfDay.Ticks - If (timeTicks = Value.Ticks) OrElse - (Value.Year = 1899 AndAlso Value.Month = 12 AndAlso Value.Day = 30) Then - Return Value.ToString("T") - ElseIf timeTicks = 0 Then - Return Value.ToString("d") - Else - Return Value.ToString("G") - End If + + + Public Shared Shadows Function ToString(ByVal Value As UInteger) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Decimal) As String - Return Value.ToString("G") + + Public Shared Shadows Function ToString(ByVal Value As Long) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Object) As String - If Value Is Nothing Then - Return Nothing - Else - Dim stringValue As String = TryCast(Value, String) - If stringValue IsNot Nothing Then - Return stringValue - End If - End If - If TypeOf Value Is Global.System.Enum Then - Value = GetEnumValue(Value) - End If - If TypeOf Value Is Boolean Then - Return CStr(DirectCast(Value, Boolean)) - ElseIf TypeOf Value Is SByte Then - Return CStr(DirectCast(Value, SByte)) - ElseIf TypeOf Value Is Byte Then - Return CStr(DirectCast(Value, Byte)) - ElseIf TypeOf Value Is Global.System.Int16 Then - Return CStr(DirectCast(Value, Global.System.Int16)) - ElseIf TypeOf Value Is Global.System.UInt16 Then - Return CStr(DirectCast(Value, Global.System.UInt16)) - ElseIf TypeOf Value Is Global.System.Int32 Then - Return CStr(DirectCast(Value, Global.System.Int32)) - ElseIf TypeOf Value Is Global.System.UInt32 Then - Return CStr(DirectCast(Value, Global.System.UInt32)) - ElseIf TypeOf Value Is Global.System.Int64 Then - Return CStr(DirectCast(Value, Global.System.Int64)) - ElseIf TypeOf Value Is Global.System.UInt64 Then - Return CStr(DirectCast(Value, Global.System.UInt64)) - ElseIf TypeOf Value Is Decimal Then - Return CStr(DirectCast(Value, Global.System.Decimal)) - ElseIf TypeOf Value Is Single Then - Return CStr(DirectCast(Value, Single)) - ElseIf TypeOf Value Is Double Then - Return CStr(DirectCast(Value, Double)) - ElseIf TypeOf Value Is Char Then - Return CStr(DirectCast(Value, Char)) - ElseIf TypeOf Value Is Date Then - Return CStr(DirectCast(Value, Date)) - Else - Dim charArray As Char() = TryCast(Value, Char()) - If charArray IsNot Nothing Then - Return New String(charArray) - End If - End If - Throw New Global.System.InvalidCastException() + + + Public Shared Shadows Function ToString(ByVal Value As ULong) As String + Return Value.ToString(Nothing, Nothing) End Function - Public Shared Shadows Function ToString(Value As Boolean) As String - If Value Then - Return Global.System.Boolean.TrueString - Else - Return Global.System.Boolean.FalseString - End If + + Public Shared Shadows Function ToString(ByVal Value As Single) As String + Return ToString(Value, Nothing) End Function - Public Shared Shadows Function ToString(Value As Byte) As String - Return Value.ToString() + + Public Shared Shadows Function ToString(ByVal Value As Double) As String + Return ToString(Value, Nothing) End Function - Public Shared Shadows Function ToString(Value As Char) As String - Return Value.ToString() + + Public Shared Shadows Function ToString(ByVal Value As Single, ByVal NumberFormat As NumberFormatInfo) As String + Return Value.ToString(Nothing, NumberFormat) End Function - Friend Shared Function GetCultureInfo() As Global.System.Globalization.CultureInfo - Return Global.System.Globalization.CultureInfo.CurrentCulture - End Function - Friend Shared Function ToHalfwidthNumbers(s As String, culture As Global.System.Globalization.CultureInfo) As String - Return s - End Function - Friend Shared Function IsHexOrOctValue(value As String, ByRef i64Value As Global.System.Int64) As Boolean - Dim ch As Char - Dim length As Integer - Dim firstNonspace As Integer - Dim tmpValue As String - length = value.Length - Do While (firstNonspace < length) - ch = value.Chars(firstNonspace) - If ch = "&"c AndAlso firstNonspace + 2 < length Then - GoTo GetSpecialValue - End If - If ch <> Strings.ChrW(32) AndAlso ch <> Strings.ChrW(&H3000) Then - Return False - End If - firstNonspace += 1 - Loop - Return False -GetSpecialValue: - ch = Global.System.Char.ToLowerInvariant(value.Chars(firstNonspace + 1)) - tmpValue = ToHalfwidthNumbers(value.Substring(firstNonspace + 2), GetCultureInfo()) - If ch = "h"c Then - i64Value = Global.System.Convert.ToInt64(tmpValue, 16) - ElseIf ch = "o"c Then - i64Value = Global.System.Convert.ToInt64(tmpValue, 8) - Else - Throw New Global.System.FormatException - End If - Return True - End Function - - Friend Shared Function IsHexOrOctValue(value As String, ByRef ui64Value As Global.System.UInt64) As Boolean - Dim ch As Char - Dim length As Integer - Dim firstNonspace As Integer - Dim tmpValue As String - length = value.Length - Do While (firstNonspace < length) - ch = value.Chars(firstNonspace) - If ch = "&"c AndAlso firstNonspace + 2 < length Then - GoTo GetSpecialValue - End If - If ch <> Strings.ChrW(32) AndAlso ch <> Strings.ChrW(&H3000) Then - Return False - End If - firstNonspace += 1 - Loop - Return False -GetSpecialValue: - ch = Global.System.Char.ToLowerInvariant(value.Chars(firstNonspace + 1)) - tmpValue = ToHalfwidthNumbers(value.Substring(firstNonspace + 2), GetCultureInfo()) - If ch = "h"c Then - ui64Value = Global.System.Convert.ToUInt64(tmpValue, 16) - ElseIf ch = "o"c Then - ui64Value = Global.System.Convert.ToUInt64(tmpValue, 8) + + Public Shared Shadows Function ToString(ByVal Value As Double, ByVal NumberFormat As NumberFormatInfo) As String + Return Value.ToString("G", NumberFormat) + End Function + + Public Shared Shadows Function ToString(ByVal Value As Date) As String + Dim TimeTicks As Long = Value.TimeOfDay.Ticks + + If (TimeTicks = Value.Ticks) OrElse + (Value.Year = 1899 AndAlso Value.Month = 12 AndAlso Value.Day = 30) Then 'OA Date with no date is 1899-12-30 + 'No date (1/1/1) + 'VSW 395746: Can't change OA DATE now because of backwards compatibility. + Return Value.ToString("T", Nothing) + ElseIf TimeTicks = 0 Then + 'No time, or is midnight + Return Value.ToString("d", Nothing) Else - Throw New Global.System.FormatException + Return Value.ToString("G", Nothing) End If - Return True End Function - Public Shared Function ToGenericParameter(Of T)(Value As Object) As T + + Public Shared Shadows Function ToString(ByVal Value As Decimal) As String + Return ToString(Value, Nothing) + End Function + + Public Shared Shadows Function ToString(ByVal Value As Decimal, ByVal NumberFormat As NumberFormatInfo) As String + Return Value.ToString("G", NumberFormat) + End Function + + Public Shared Shadows Function ToString(ByVal Value As Object) As String + If Value Is Nothing Then Return Nothing - End If - Dim reflectedType As Global.System.Type = GetType(T) - If Global.System.Type.Equals(reflectedType, GetType(Global.System.Boolean)) Then - Return DirectCast(CObj(CBool(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.SByte)) Then - Return DirectCast(CObj(CSByte(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Byte)) Then - Return DirectCast(CObj(CByte(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Int16)) Then - Return DirectCast(CObj(CShort(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.UInt16)) Then - Return DirectCast(CObj(CUShort(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Int32)) Then - Return DirectCast(CObj(CInt(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.UInt32)) Then - Return DirectCast(CObj(CUInt(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Int64)) Then - Return DirectCast(CObj(CLng(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.UInt64)) Then - Return DirectCast(CObj(CULng(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Decimal)) Then - Return DirectCast(CObj(CDec(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Single)) Then - Return DirectCast(CObj(CSng(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Double)) Then - Return DirectCast(CObj(CDbl(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.DateTime)) Then - Return DirectCast(CObj(CDate(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.Char)) Then - Return DirectCast(CObj(CChar(Value)), T) - ElseIf Global.System.Type.Equals(reflectedType, GetType(Global.System.String)) Then - Return DirectCast(CObj(CStr(Value)), T) + Else - Return DirectCast(Value, T) + Dim StringValue As String = TryCast(Value, String) + + If StringValue IsNot Nothing Then + Return StringValue + End If End If - End Function - Private Shared Function CastSByteEnum(ByVal expression As SByte, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + Dim ValueInterface As IConvertible + Dim ValueTypeCode As TypeCode - Private Shared Function CastByteEnum(ByVal expression As Byte, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + ValueInterface = TryCast(Value, IConvertible) - Private Shared Function CastInt16Enum(ByVal expression As Int16, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + If Not ValueInterface Is Nothing Then - Private Shared Function CastUInt16Enum(ByVal expression As UInt16, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + ValueTypeCode = ValueInterface.GetTypeCode() - Private Shared Function CastInt32Enum(ByVal expression As Int32, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + Select Case ValueTypeCode + Case TypeCode.Boolean + Return CStr(ValueInterface.ToBoolean(Nothing)) - Private Shared Function CastUInt32Enum(ByVal expression As UInt32, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + Case TypeCode.SByte + Return CStr(ValueInterface.ToSByte(Nothing)) - Private Shared Function CastInt64Enum(ByVal expression As Int64, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + Case TypeCode.Byte + Return CStr(ValueInterface.ToByte(Nothing)) - Private Shared Function CastUInt64Enum(ByVal expression As UInt64, ByVal targetType As Type) As Object - If IsEnum(targetType) Then Return System.Enum.ToObject(targetType, expression) - Return expression - End Function + Case TypeCode.Int16 + Return CStr(ValueInterface.ToInt16(Nothing)) + + Case TypeCode.UInt16 + Return CStr(ValueInterface.ToUInt16(Nothing)) + + Case TypeCode.Int32 + Return CStr(ValueInterface.ToInt32(Nothing)) + + Case TypeCode.UInt32 + Return CStr(ValueInterface.ToUInt32(Nothing)) + + Case TypeCode.Int64 + Return CStr(ValueInterface.ToInt64(Nothing)) + + Case TypeCode.UInt64 + Return CStr(ValueInterface.ToUInt64(Nothing)) + + Case TypeCode.Decimal + Return CStr(ValueInterface.ToDecimal(Nothing)) + + Case TypeCode.Single + Return CStr(ValueInterface.ToSingle(Nothing)) + + Case TypeCode.Double + Return CStr(ValueInterface.ToDouble(Nothing)) - Friend Shared Function ForceValueCopy(ByVal expression As Object, ByVal targetType As Type) As Object - 'Is there any way to get this faster? It's called every time we pass a valuetype to a byref parameter. + Case TypeCode.Char + Return CStr(ValueInterface.ToChar(Nothing)) - If expression Is Nothing Then - Return expression + Case TypeCode.DateTime + Return CStr(ValueInterface.ToDateTime(Nothing)) + + Case TypeCode.String + Return CStr(ValueInterface.ToString(Nothing)) + + Case Else + ' Fall through to error + End Select + + Else + Dim CharArray As Char() = TryCast(Value, Char()) + + If CharArray IsNot Nothing Then + Return New String(CharArray) + End If End If - Dim tyCode As TypeCode = expression.GetType().GetTypeCode + Throw New InvalidCastException(SR.Format(SR.InvalidCast_FromTo, VBFriendlyName(Value), "String")) + + End Function + + Public Shared Function ToGenericParameter(Of T)(ByVal Value As Object) As T + + 'Think carefully about this function and how it handles Enums, + 'System.Enum, System.ValueType, Object, etc. This function should not + 'do a latebound conversion. - Debug.Assert(tyCode = GetTypeCode(targetType), "expected types to match") + If Value Is Nothing Then + Return Nothing + End If - Select Case tyCode + Dim ReflectedType As Type = GetType(T) + Dim tc As TypeCode = GetTypeCode(ReflectedType) + Select Case tc Case TypeCode.Boolean - Return Convert.ToBoolean(expression) + Return DirectCast(CObj(CBool(Value)), T) Case TypeCode.SByte - Return CastSByteEnum(Convert.ToSByte(expression), targetType) + Return DirectCast(CObj(CSByte(Value)), T) Case TypeCode.Byte - Return CastByteEnum(Convert.ToByte(expression), targetType) + Return DirectCast(CObj(CByte(Value)), T) Case TypeCode.Int16 - Return CastInt16Enum(Convert.ToInt16(expression), targetType) + Return DirectCast(CObj(CShort(Value)), T) Case TypeCode.UInt16 - Return CastUInt16Enum(Convert.ToUInt16(expression), targetType) + Return DirectCast(CObj(CUShort(Value)), T) Case TypeCode.Int32 - Return CastInt32Enum(Convert.ToInt32(expression), targetType) + Return DirectCast(CObj(CInt(Value)), T) Case TypeCode.UInt32 - Return CastUInt32Enum(Convert.ToUInt32(expression), targetType) + Return DirectCast(CObj(CUInt(Value)), T) Case TypeCode.Int64 - Return CastInt64Enum(Convert.ToInt64(expression), targetType) + Return DirectCast(CObj(CLng(Value)), T) Case TypeCode.UInt64 - Return CastUInt64Enum(Convert.ToUInt64(expression), targetType) + Return DirectCast(CObj(CULng(Value)), T) Case TypeCode.Decimal - Return Convert.ToDecimal(expression) + Return DirectCast(CObj(CDec(Value)), T) Case TypeCode.Single - Return Convert.ToSingle(expression) + Return DirectCast(CObj(CSng(Value)), T) Case TypeCode.Double - Return Convert.ToDouble(expression) + Return DirectCast(CObj(CDbl(Value)), T) Case TypeCode.DateTime - Return Convert.ToDateTime(expression) + Return DirectCast(CObj(CDate(Value)), T) Case TypeCode.Char - Return Convert.ToChar(expression) + Return DirectCast(CObj(CChar(Value)), T) + Case TypeCode.String + Return DirectCast(CObj(CStr(Value)), T) + Case Else + Return DirectCast(Value, T) + End Select + End Function + + Private Shared Function CastSByteEnum(ByVal Expression As SByte, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastByteEnum(ByVal Expression As Byte, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastInt16Enum(ByVal Expression As Int16, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastUInt16Enum(ByVal Expression As UInt16, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastInt32Enum(ByVal Expression As Int32, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastUInt32Enum(ByVal Expression As UInt32, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastInt64Enum(ByVal Expression As Int64, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Private Shared Function CastUInt64Enum(ByVal Expression As UInt64, ByVal TargetType As Type) As Object + If IsEnum(TargetType) Then Return [Enum].ToObject(TargetType, Expression) + Return Expression + End Function + + Friend Shared Function ForceValueCopy(ByVal Expression As Object, ByVal TargetType As Type) As Object + + Dim iconv As IConvertible = TryCast(Expression, IConvertible) + + If iconv Is Nothing Then + Return Expression + End If + + Debug.Assert(iconv.GetTypeCode = GetTypeCode(TargetType), "expected types to match") + + Select Case iconv.GetTypeCode() + + Case TypeCode.Boolean : Return iconv.ToBoolean(Nothing) + Case TypeCode.SByte : Return CastSByteEnum(iconv.ToSByte(Nothing), TargetType) + Case TypeCode.Byte : Return CastByteEnum(iconv.ToByte(Nothing), TargetType) + Case TypeCode.Int16 : Return CastInt16Enum(iconv.ToInt16(Nothing), TargetType) + Case TypeCode.UInt16 : Return CastUInt16Enum(iconv.ToUInt16(Nothing), TargetType) + Case TypeCode.Int32 : Return CastInt32Enum(iconv.ToInt32(Nothing), TargetType) + Case TypeCode.UInt32 : Return CastUInt32Enum(iconv.ToUInt32(Nothing), TargetType) + Case TypeCode.Int64 : Return CastInt64Enum(iconv.ToInt64(Nothing), TargetType) + Case TypeCode.UInt64 : Return CastUInt64Enum(iconv.ToUInt64(Nothing), TargetType) + Case TypeCode.Decimal : Return iconv.ToDecimal(Nothing) + Case TypeCode.Single : Return iconv.ToSingle(Nothing) + Case TypeCode.Double : Return iconv.ToDouble(Nothing) + Case TypeCode.DateTime : Return iconv.ToDateTime(Nothing) + Case TypeCode.Char : Return iconv.ToChar(Nothing) Case TypeCode.Empty - Debug.Assert(False, "shouldn't reach here") + Debug.Fail("shouldn't reach here") Case TypeCode.Object, + TypeCode.DBNull, TypeCode.String 'fall through + End Select - Return expression + Return Expression + End Function - Private Shared Function ChangeIntrinsicType(ByVal expression As Object, ByVal targetType As Type) As Object + Private Shared Function ChangeIntrinsicType(ByVal Expression As Object, ByVal TargetType As Type) As Object 'This function will not handle user-defined conversion resolution, and so handles 'only conversions between intrinsic types. - Debug.Assert(IsIntrinsicType(expression.GetType) OrElse IsEnum(expression.GetType), "this function converts between intrinsic types only") - - Select Case GetTypeCode(targetType) - - Case TypeCode.Boolean : Return CBool(expression) - Case TypeCode.SByte : Return CastSByteEnum(CSByte(expression), targetType) - Case TypeCode.Byte : Return CastByteEnum(CByte(expression), targetType) - Case TypeCode.Int16 : Return CastInt16Enum(CShort(expression), targetType) - Case TypeCode.UInt16 : Return CastUInt16Enum(CUShort(expression), targetType) - Case TypeCode.Int32 : Return CastInt32Enum(CInt(expression), targetType) - Case TypeCode.UInt32 : Return CastUInt32Enum(CUInt(expression), targetType) - Case TypeCode.Int64 : Return CastInt64Enum(CLng(expression), targetType) - Case TypeCode.UInt64 : Return CastUInt64Enum(CULng(expression), targetType) - Case TypeCode.Decimal : Return CDec(expression) - Case TypeCode.Single : Return CSng(expression) - Case TypeCode.Double : Return CDbl(expression) - Case TypeCode.DateTime : Return CDate(expression) - Case TypeCode.Char : Return CChar(expression) - Case TypeCode.String : Return CStr(expression) + Debug.Assert(IsIntrinsicType(Expression.GetType) OrElse IsEnum(Expression.GetType), "this function converts between intrinsic types only") + + Select Case GetTypeCode(TargetType) + + Case TypeCode.Boolean : Return CBool(Expression) + Case TypeCode.SByte : Return CastSByteEnum(CSByte(Expression), TargetType) + Case TypeCode.Byte : Return CastByteEnum(CByte(Expression), TargetType) + Case TypeCode.Int16 : Return CastInt16Enum(CShort(Expression), TargetType) + Case TypeCode.UInt16 : Return CastUInt16Enum(CUShort(Expression), TargetType) + Case TypeCode.Int32 : Return CastInt32Enum(CInt(Expression), TargetType) + Case TypeCode.UInt32 : Return CastUInt32Enum(CUInt(Expression), TargetType) + Case TypeCode.Int64 : Return CastInt64Enum(CLng(Expression), TargetType) + Case TypeCode.UInt64 : Return CastUInt64Enum(CULng(Expression), TargetType) + Case TypeCode.Decimal : Return CDec(Expression) + Case TypeCode.Single : Return CSng(Expression) + Case TypeCode.Double : Return CDbl(Expression) + Case TypeCode.DateTime : Return CDate(Expression) + Case TypeCode.Char : Return CChar(Expression) + Case TypeCode.String : Return CStr(Expression) Case TypeCode.Empty, - TypeCode.Object - 'fall through to error + TypeCode.Object, + TypeCode.DBNull + 'fall though to error End Select - Debug.Assert(False, "Expected intrinsic type only, not: " & targetType.Name) + Debug.Fail("Expected intrinsic type only, not: " & TargetType.Name) Throw New Exception 'would be nice to have an internal runtime exception or something like that End Function - - Public Shared Function ChangeType(ByVal Expression As Object, ByVal TargetType As System.Type) As Object + Public Shared Function ChangeType(ByVal Expression As Object, ByVal TargetType As Type) As Object Return ChangeType(Expression, TargetType, False) End Function - - Friend Shared Function ChangeType(ByVal expression As Object, ByVal targetType As System.Type, ByVal dynamic As Boolean) As Object - If targetType Is Nothing Then - Throw New ArgumentException(GetResourceString(SR.Argument_InvalidNullValue1, "TargetType")) + + Friend Shared Function ChangeType(ByVal Expression As Object, ByVal TargetType As Type, ByVal Dynamic As Boolean) As Object + If TargetType Is Nothing Then + Throw New ArgumentException(SR.Format(SR.Argument_InvalidNullValue1, "TargetType")) End If - If expression Is Nothing Then - If IsValueType(targetType) Then + If Expression Is Nothing Then + If IsValueType(TargetType) Then 'method.invoke will do this for us, so when casting arguments to param types during 'latebinding, the createinstance call isn't needed, but ChangeType used in a generalized 'manner should return a default instance. - Return Activator.CreateInstance(targetType) + Return Activator.CreateInstance(TargetType) Else Return Nothing End If End If - Dim sourceType As Type = expression.GetType - Debug.Assert(Not sourceType.IsByRef, "never expected to see byref source type") + Dim SourceType As Type = Expression.GetType + Debug.Assert(Not SourceType.IsByRef, "never expected to see byref source type") 'Dig through ByRef types which might come in. - If targetType.IsByRef Then targetType = targetType.GetElementType + If TargetType.IsByRef Then TargetType = TargetType.GetElementType - If targetType Is sourceType OrElse IsRootObjectType(targetType) Then - Return expression + If TargetType Is SourceType OrElse IsRootObjectType(TargetType) Then + Return Expression End If - Dim targetTypeCode As TypeCode = GetTypeCode(targetType) + Dim TargetTypeCode As TypeCode = GetTypeCode(TargetType) 'All conversions between intrinsic types are natively built-in 'and require no user-defined conversion resolution. - If IsIntrinsicType(targetTypeCode) Then - Dim sourceTypeCode As TypeCode = GetTypeCode(sourceType) - If IsIntrinsicType(sourceTypeCode) Then - Return ChangeIntrinsicType(expression, targetType) + If IsIntrinsicType(TargetTypeCode) Then + Dim SourceTypeCode As TypeCode = GetTypeCode(SourceType) + If IsIntrinsicType(SourceTypeCode) Then + Return ChangeIntrinsicType(Expression, TargetType) End If End If - If targetType.IsInstanceOfType(expression) Then - Return expression + If TargetType.IsInstanceOfType(Expression) Then + Return Expression End If - If IsCharArrayRankOne(targetType) AndAlso IsStringType(sourceType) Then - Return CType(DirectCast(expression, String), Char()) + If IsCharArrayRankOne(TargetType) AndAlso IsStringType(SourceType) Then + Return CType(DirectCast(Expression, String), Char()) End If - If IsStringType(targetType) AndAlso IsCharArrayRankOne(sourceType) Then - Return CStr(DirectCast(expression, Char())) + If IsStringType(TargetType) AndAlso IsCharArrayRankOne(SourceType) Then + Return CStr(DirectCast(Expression, Char())) End If - Debug.Assert(ClassifyPredefinedConversion(targetType, sourceType) = ConversionClass.None OrElse - ClassifyPredefinedConversion(targetType, sourceType) = ConversionClass.Narrowing, + Debug.Assert(ClassifyPredefinedConversion(TargetType, SourceType) = ConversionClass.None OrElse + ClassifyPredefinedConversion(TargetType, SourceType) = ConversionClass.Narrowing, "expected all predefined conversions handled by this point") - If dynamic Then - Dim idmop As System.Dynamic.IDynamicMetaObjectProvider = IDOUtils.TryCastToIDMOP(expression) + If Dynamic Then + Dim idmop As IDynamicMetaObjectProvider = IDOUtils.TryCastToIDMOP(Expression) If idmop IsNot Nothing Then - Return IDOBinder.UserDefinedConversion(idmop, targetType) + Return IDOBinder.UserDefinedConversion(idmop, TargetType) End If End If - Return ObjectUserDefinedConversion(expression, targetType) + Return ObjectUserDefinedConversion(Expression, TargetType) End Function - - + + + Public Shared Function FallbackUserDefinedConversion( - ByVal expression As Object, ByVal targetType As Type) As Object + ByVal Expression As Object, ByVal TargetType As Type) As Object - Return ObjectUserDefinedConversion(expression, targetType) - End Function + Return ObjectUserDefinedConversion(Expression, TargetType) + End Function 'FalbackUserDefinedConversion - + + Private Shared Function ObjectUserDefinedConversion( - ByVal expression As Object, ByVal targetType As Type) As Object + ByVal Expression As Object, ByVal TargetType As Type) As Object - Dim sourceType As Type = expression.GetType - If ClassifyPredefinedConversion(targetType, sourceType) = ConversionClass.None AndAlso - (IsClassOrValueType(sourceType) OrElse IsClassOrValueType(targetType)) AndAlso - Not (IsIntrinsicType(sourceType) AndAlso IsIntrinsicType(targetType)) Then + Dim SourceType As Type = Expression.GetType + If ClassifyPredefinedConversion(TargetType, SourceType) = ConversionClass.None AndAlso + (IsClassOrValueType(SourceType) OrElse IsClassOrValueType(TargetType)) AndAlso + Not (IsIntrinsicType(SourceType) AndAlso IsIntrinsicType(TargetType)) Then 'Conversions of the form S-->T use only one user-defined conversion at a time, i.e., 'user-defined conversions are not chained together. It may be necessary to convert to and @@ -1320,42 +2592,41 @@ GetSpecialValue: 'invocation to the target type, i.e., Tx-->T. 'Resolve the operator. - Dim operatorMethod As Method = Nothing - Dim result As ConversionClass = - ClassifyUserDefinedConversion(targetType, sourceType, operatorMethod) + Dim OperatorMethod As Method = Nothing + Dim Result As ConversionClass = + ClassifyUserDefinedConversion(TargetType, SourceType, OperatorMethod) - If operatorMethod IsNot Nothing Then - Debug.Assert(result = ConversionClass.Widening OrElse result = ConversionClass.Narrowing, + If OperatorMethod IsNot Nothing Then + Debug.Assert(Result = ConversionClass.Widening OrElse Result = ConversionClass.Narrowing, "operator method not expected for invalid conversion") 'Invoke the operator. This handles the conversion S-->Sx. - Dim baseReference As Container = New Container(operatorMethod.DeclaringType) - Dim invocationResult As Object = - baseReference.InvokeMethod( - operatorMethod, - New Object() {expression}, + Dim BaseReference As Symbols.Container = New Symbols.Container(OperatorMethod.DeclaringType) + Dim InvocationResult As Object = + BaseReference.InvokeMethod( + OperatorMethod, + New Object() {Expression}, Nothing, - BindingFlagsInvokeMethod) + BindingFlags.InvokeMethod) 'Now convert the result of the invocation to the target type, Tx-->T. #If DEBUG Then - If invocationResult IsNot Nothing Then - + If InvocationResult IsNot Nothing Then - 'Disabling the assert below when we're converting to Nullable(Of T) + 'disabling the assert below when we're converting to Nullable(Of T) 'since the Runtime hasn't been updated yet to handle Nullable. In this case the assert 'is harmless, but ClassifyPredefinedConversion hasn't been updated to consider Nullable conversions, 'and updating this across the entire runtime would be significant feature work. - If Not (targetType.IsGenericType AndAlso - Not targetType.IsGenericTypeDefinition AndAlso - targetType.GetGenericTypeDefinition().Equals(GetType(Nullable(Of ))) AndAlso - targetType.GetGenericArguments().Length > 0 AndAlso - invocationResult.GetType().Equals(targetType.GetGenericArguments()(0))) Then + If Not _ + (TargetType.IsGenericType AndAlso + Not TargetType.IsGenericTypeDefinition AndAlso + TargetType.GetGenericTypeDefinition().Equals(GetType(Nullable(Of ))) AndAlso + TargetType.GetGenericArguments().Length > 0 AndAlso + InvocationResult.GetType().Equals(TargetType.GetGenericArguments()(0))) Then - - Dim PostConversion As ConversionClass = ClassifyPredefinedConversion(targetType, invocationResult.GetType) + Dim PostConversion As ConversionClass = ClassifyPredefinedConversion(TargetType, InvocationResult.GetType) Debug.Assert( PostConversion = ConversionClass.Narrowing OrElse @@ -1365,14 +2636,14 @@ GetSpecialValue: End If End If #End If - Return ChangeType(invocationResult, targetType) + Return ChangeType(InvocationResult, TargetType) - ElseIf result = ConversionClass.Ambiguous Then + ElseIf Result = ConversionClass.Ambiguous Then Throw New InvalidCastException( GetResourceString( SR.AmbiguousCast2, - VBFriendlyName(sourceType), - VBFriendlyName(targetType))) + VBFriendlyName(SourceType), + VBFriendlyName(TargetType))) End If End If @@ -1380,30 +2651,31 @@ GetSpecialValue: Throw New InvalidCastException( GetResourceString( SR.InvalidCast_FromTo, - VBFriendlyName(sourceType), - VBFriendlyName(targetType))) + VBFriendlyName(SourceType), + VBFriendlyName(TargetType))) - End Function + End Function 'UserDefinedConversion ' Simplied version of ObjectUserDefinedConversion, above ' Determines if conversion is possible - Friend Shared Function CanUserDefinedConvert(ByVal expression As Object, ByVal targetType As Type) As Boolean + Friend Shared Function CanUserDefinedConvert(ByVal Expression As Object, ByVal TargetType As Type) As Boolean - Dim sourceType As Type = expression.GetType - If ClassifyPredefinedConversion(targetType, sourceType) = ConversionClass.None AndAlso - (IsClassOrValueType(sourceType) OrElse IsClassOrValueType(targetType)) AndAlso - Not (IsIntrinsicType(sourceType) AndAlso IsIntrinsicType(targetType)) Then + Dim SourceType As Type = Expression.GetType + If ClassifyPredefinedConversion(TargetType, SourceType) = ConversionClass.None AndAlso + (IsClassOrValueType(SourceType) OrElse IsClassOrValueType(TargetType)) AndAlso + Not (IsIntrinsicType(SourceType) AndAlso IsIntrinsicType(TargetType)) Then 'Resolve the operator. - Dim operatorMethod As Method = Nothing - Dim result As ConversionClass = - ClassifyUserDefinedConversion(targetType, sourceType, operatorMethod) + Dim OperatorMethod As Method = Nothing + Dim Result As ConversionClass = + ClassifyUserDefinedConversion(TargetType, SourceType, OperatorMethod) - Return operatorMethod IsNot Nothing + Return OperatorMethod IsNot Nothing End If Return False - End Function + End Function 'CanUserDefinedConvert End Class + End Namespace diff --git a/src/Microsoft.VisualBasic/tests/ConversionsTests.cs b/src/Microsoft.VisualBasic/tests/ConversionsTests.cs index 05399cd3c47c..a2f5ca198a4b 100644 --- a/src/Microsoft.VisualBasic/tests/ConversionsTests.cs +++ b/src/Microsoft.VisualBasic/tests/ConversionsTests.cs @@ -14,6 +14,29 @@ namespace Microsoft.VisualBasic.Tests { public class ConversionsTests { + private static bool? s_reflectionEmitSupported = null; + + public static bool ReflectionEmitSupported + { + get + { + if (s_reflectionEmitSupported == null) + { + try + { + object o = FloatEnum; + s_reflectionEmitSupported = true; + } + catch (PlatformNotSupportedException) + { + s_reflectionEmitSupported = false; + } + } + + return s_reflectionEmitSupported.Value; + } + } + public static IEnumerable InvalidString_TestData() { yield return new object[] { "" }; @@ -27,22 +50,10 @@ public static IEnumerable InvalidString_TestData() public static IEnumerable InvalidBool_TestData() { - if (PlatformDetection.IsReflectionEmitSupported) + if (ReflectionEmitSupported) { - object floatEnum = null; - try - { - floatEnum = FloatEnum; - } - catch (PlatformNotSupportedException) - { - yield break; - } - - yield return new object[] { floatEnum }; + yield return new object[] { FloatEnum }; yield return new object[] { DoubleEnum }; - yield return new object[] { BoolEnum }; - yield return new object[] { CharEnum }; yield return new object[] { IntPtrEnum }; yield return new object[] { UIntPtrEnum }; } @@ -55,6 +66,10 @@ public static IEnumerable InvalidNumberObject_TestData() yield return new object[] { char.MaxValue }; yield return new object[] { new DateTime(10) }; yield return new object[] { new object() }; + if (ReflectionEmitSupported) + { + yield return new object[] { CharEnum }; + } } public static IEnumerable ToByte_String_TestData() @@ -168,6 +183,10 @@ public static IEnumerable ToByte_Object_TestData() // bool. yield return new object[] { true, byte.MaxValue }; yield return new object[] { false, byte.MinValue }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, byte.MinValue }; + } // null. yield return new object[] { null, byte.MinValue }; @@ -176,20 +195,30 @@ public static IEnumerable ToByte_Object_TestData() [Theory] [MemberData(nameof(ToByte_Object_TestData))] [MemberData(nameof(ToByte_String_TestData))] - public void ToByte_Object_ReturnsExpected(object value, byte expected) + public void ToByte_Object_ReturnsExpected(IConvertible value, byte expected) { AssertEqual(expected, Conversions.ToByte(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToByte(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToByte_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToByte(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToByte_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToByte(value)); + } + public static IEnumerable ToByte_OverflowObject_TestData() { yield return new object[] { ushort.MaxValue }; @@ -335,6 +364,10 @@ public static IEnumerable ToSByte_Object_TestData() // bool. yield return new object[] { true, (sbyte)(-1) }; yield return new object[] { false, (sbyte)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (sbyte)0 }; + } // null. yield return new object[] { null, (sbyte)0 }; @@ -343,20 +376,30 @@ public static IEnumerable ToSByte_Object_TestData() [Theory] [MemberData(nameof(ToSByte_Object_TestData))] [MemberData(nameof(ToSByte_String_TestData))] - public void ToSByte_Object_ReturnsExpected(object value, sbyte expected) + public void ToSByte_Object_ReturnsExpected(IConvertible value, sbyte expected) { AssertEqual(expected, Conversions.ToSByte(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToSByte(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToSByte_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToSByte(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToSByte_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToSByte(value)); + } + public static IEnumerable ToSByte_OverflowObject_TestData() { yield return new object[] { byte.MaxValue }; @@ -495,6 +538,10 @@ public static IEnumerable ToUShort_Object_TestData() // bool. yield return new object[] { true, ushort.MaxValue }; yield return new object[] { false, ushort.MinValue }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, ushort.MinValue }; + } // null. yield return new object[] { null, ushort.MinValue }; @@ -503,20 +550,30 @@ public static IEnumerable ToUShort_Object_TestData() [Theory] [MemberData(nameof(ToUShort_Object_TestData))] [MemberData(nameof(ToUShort_String_TestData))] - public void ToUShort_Object_ReturnsExpected(object value, ushort expected) + public void ToUShort_Object_ReturnsExpected(IConvertible value, ushort expected) { AssertEqual(expected, Conversions.ToUShort(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToUShort(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToUShort_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToUShort(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToUShort_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToUShort(value)); + } + public static IEnumerable ToUShort_OverflowObject_TestData() { yield return new object[] { int.MaxValue }; @@ -665,6 +722,10 @@ public static IEnumerable ToShort_Object_TestData() // bool. yield return new object[] { true, (short)(-1) }; yield return new object[] { false, (short)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (short)0 }; + } // null. yield return new object[] { null, (short)0 }; @@ -673,20 +734,30 @@ public static IEnumerable ToShort_Object_TestData() [Theory] [MemberData(nameof(ToShort_Object_TestData))] [MemberData(nameof(ToShort_String_TestData))] - public void ToShort_Object_ReturnsExpected(object value, short expected) + public void ToShort_Object_ReturnsExpected(IConvertible value, short expected) { AssertEqual(expected, Conversions.ToShort(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToShort(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToShort_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToShort(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToShort_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToShort(value)); + } + public static IEnumerable ToShort_OverflowObject_TestData() { yield return new object[] { ushort.MaxValue }; @@ -829,6 +900,10 @@ public static IEnumerable ToUInteger_Object_TestData() // bool. yield return new object[] { true, uint.MaxValue }; yield return new object[] { false, uint.MinValue }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, uint.MinValue }; + } // null. yield return new object[] { null, uint.MinValue }; @@ -837,20 +912,30 @@ public static IEnumerable ToUInteger_Object_TestData() [Theory] [MemberData(nameof(ToUInteger_Object_TestData))] [MemberData(nameof(ToUInteger_String_TestData))] - public void ToUInteger_Object_ReturnsExpected(object value, uint expected) + public void ToUInteger_Object_ReturnsExpected(IConvertible value, uint expected) { AssertEqual(expected, Conversions.ToUInteger(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToUInteger(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToUInteger_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToUInteger(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToUInteger_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToUInteger(value)); + } + public static IEnumerable ToUInteger_OverflowObject_TestData() { yield return new object[] { ulong.MaxValue }; @@ -1005,6 +1090,10 @@ public static IEnumerable ToInteger_Object_TestData() // bool. yield return new object[] { true, -1 }; yield return new object[] { false, 0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, 0 }; + } // null. yield return new object[] { null, 0 }; @@ -1013,20 +1102,30 @@ public static IEnumerable ToInteger_Object_TestData() [Theory] [MemberData(nameof(ToInteger_Object_TestData))] [MemberData(nameof(ToInteger_String_TestData))] - public void ToInteger_Object_ReturnsExpected(object value, int expected) + public void ToInteger_Object_ReturnsExpected(IConvertible value, int expected) { AssertEqual(expected, Conversions.ToInteger(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToInteger(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToInteger_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToInteger(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToInteger_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToInteger(value)); + } + public static IEnumerable ToInteger_OverflowObject_TestData() { yield return new object[] { uint.MaxValue }; @@ -1177,6 +1276,10 @@ public static IEnumerable ToULong_Object_TestData() // bool. yield return new object[] { true, ulong.MaxValue }; yield return new object[] { false, ulong.MinValue }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, ulong.MinValue }; + } // null. yield return new object[] { null, ulong.MinValue }; @@ -1185,21 +1288,31 @@ public static IEnumerable ToULong_Object_TestData() [Theory] [MemberData(nameof(ToULong_Object_TestData))] [MemberData(nameof(ToULong_String_TestData))] - public void ToULong_Object_ReturnsExpected(object value, ulong expected) + public void ToULong_Object_ReturnsExpected(IConvertible value, ulong expected) { AssertEqual(expected, Conversions.ToULong(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToULong(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(ToULong_InvalidString_TestData))] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToULong_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToULong(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToULong_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToULong(value)); + } + public static IEnumerable ToULong_OverflowObject_TestData() { yield return new object[] { sbyte.MinValue }; @@ -1391,6 +1504,10 @@ public static IEnumerable ToLong_Object_TestData() // bool. yield return new object[] { true, (long)(-1) }; yield return new object[] { false, (long)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (long)0 }; + } // null. yield return new object[] { null, (long)0 }; @@ -1399,9 +1516,13 @@ public static IEnumerable ToLong_Object_TestData() [Theory] [MemberData(nameof(ToLong_Object_TestData))] [MemberData(nameof(ToLong_String_TestData))] - public void ToLong_Object_ReturnsExpected(object value, long expected) + public void ToLong_Object_ReturnsExpected(IConvertible value, long expected) { AssertEqual(expected, Conversions.ToLong(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToLong(new ConvertibleWrapper(value))); + } } public static IEnumerable ToLong_InvalidObject_TestData() @@ -1415,12 +1536,18 @@ public static IEnumerable ToLong_InvalidObject_TestData() [MemberData(nameof(ToLong_InvalidObject_TestData))] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToLong_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToLong(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToLong_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToLong(value)); + } + public static IEnumerable ToLong_OverflowObject_TestData() { yield return new object[] { ulong.MaxValue }; @@ -1603,6 +1730,10 @@ public static IEnumerable ToSingle_Object_TestData() // bool. yield return new object[] { true, (float)(-1) }; yield return new object[] { false, (float)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (float)0 }; + } // null. yield return new object[] { null, (float)0 }; @@ -1611,20 +1742,30 @@ public static IEnumerable ToSingle_Object_TestData() [Theory] [MemberData(nameof(ToSingle_Object_TestData))] [MemberData(nameof(ToSingle_String_TestData))] - public void ToSingle_Object_ReturnsExpected(object value, float expected) + public void ToSingle_Object_ReturnsExpected(IConvertible value, float expected) { AssertEqual(expected, Conversions.ToSingle(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToSingle(new ConvertibleWrapper(value))); + } } [Theory] [MemberData(nameof(InvalidNumberObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToSingle_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToSingle(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToSingle_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToSingle(value)); + } + public static IEnumerable ToSingle_OverflowObject_TestData() { yield return new object[] { "1844674407370955161618446744073709551616" }; @@ -1782,6 +1923,10 @@ public static IEnumerable ToDouble_Object_TestData() // bool. yield return new object[] { true, (double)(-1) }; yield return new object[] { false, (double)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (double)0 }; + } // null. yield return new object[] { null, (double)0 }; @@ -1790,9 +1935,13 @@ public static IEnumerable ToDouble_Object_TestData() [Theory] [MemberData(nameof(ToDouble_Object_TestData))] [MemberData(nameof(ToDouble_String_TestData))] - public void ToDouble_Object_ReturnsExpected(object value, double expected) + public void ToDouble_Object_ReturnsExpected(IConvertible value, double expected) { AssertEqual(expected, Conversions.ToDouble(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToDouble(new ConvertibleWrapper(value))); + } } public static IEnumerable ToDouble_InvalidObject_TestData() @@ -1807,12 +1956,18 @@ public static IEnumerable ToDouble_InvalidObject_TestData() [Theory] [MemberData(nameof(ToDouble_InvalidObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToDouble_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToDouble(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToDouble_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToDouble(value)); + } + public static IEnumerable ToDecimal_String_TestData() { yield return new object[] { null, (decimal)0 }; @@ -1964,6 +2119,10 @@ public static IEnumerable ToDecimal_Object_TestData() // bool. yield return new object[] { true, (decimal)(-1) }; yield return new object[] { false, (decimal)0 }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, (decimal)0 }; + } // null. yield return new object[] { null, (decimal)0 }; @@ -1972,9 +2131,13 @@ public static IEnumerable ToDecimal_Object_TestData() [Theory] [MemberData(nameof(ToDecimal_Object_TestData))] [MemberData(nameof(ToDecimal_String_TestData))] - public void ToDecimal_Object_ReturnsExpected(object value, decimal expected) + public void ToDecimal_Object_ReturnsExpected(IConvertible value, decimal expected) { AssertEqual(expected, Conversions.ToDecimal(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToDecimal(new ConvertibleWrapper(value))); + } } public static IEnumerable ToDecimal_InvalidObject_TestData() @@ -1992,12 +2155,18 @@ public static IEnumerable ToDecimal_InvalidObject_TestData() [Theory] [MemberData(nameof(ToDecimal_InvalidObject_TestData))] [MemberData(nameof(InvalidString_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToDecimal_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToDecimal(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToDecimal_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToDecimal(value)); + } + public static IEnumerable ToDecimal_OverflowObject_TestData() { yield return new object[] { float.MinValue }; @@ -2176,6 +2345,10 @@ public static IEnumerable ToBoolean_Object_TestData() // bool. yield return new object[] { true, true }; yield return new object[] { false, false }; + if (ReflectionEmitSupported) + { + yield return new object[] { BoolEnum, false }; + } // null. yield return new object[] { null, false }; @@ -2184,33 +2357,39 @@ public static IEnumerable ToBoolean_Object_TestData() [Theory] [MemberData(nameof(ToBoolean_Object_TestData))] [MemberData(nameof(ToBoolean_String_TestData))] - public void ToBoolean_Object_ReturnsExpected(object value, bool expected) + public void ToBoolean_Object_ReturnsExpected(IConvertible value, bool expected) { AssertEqual(expected, Conversions.ToBoolean(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToBoolean(new ConvertibleWrapper(value))); + } } public static IEnumerable ToBoolean_InvalidObject_TestData() { - yield return new object[] { char.MinValue }; - yield return new object[] { (char)1 }; - yield return new object[] { char.MaxValue }; - yield return new object[] { new DateTime(10) }; yield return new object[] { "" }; yield return new object[] { "&" }; yield return new object[] { "&a" }; yield return new object[] { "&a0" }; yield return new object[] { "invalid" }; - yield return new object[] { new object() }; } [Theory] [MemberData(nameof(ToBoolean_InvalidObject_TestData))] - [MemberData(nameof(InvalidBool_TestData))] + [MemberData(nameof(InvalidNumberObject_TestData))] public void ToBoolean_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToBoolean(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToBoolean_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToBoolean(value)); + } + public static IEnumerable ToChar_String_TestData() { yield return new object[] { null, char.MinValue }; @@ -2255,9 +2434,13 @@ public static IEnumerable ToChar_Object_TestData() [Theory] [MemberData(nameof(ToChar_Object_TestData))] [MemberData(nameof(ToChar_String_TestData))] - public void ToChar_Object_ReturnsExpected(object value, char expected) + public void ToChar_Object_ReturnsExpected(IConvertible value, char expected) { AssertEqual(expected, Conversions.ToChar(value)); + if (value != null) + { + AssertEqual(expected, Conversions.ToChar(new ConvertibleWrapper(value))); + } } public static IEnumerable ToChar_InvalidObject_TestData() @@ -2357,12 +2540,18 @@ public static IEnumerable ToChar_InvalidObject_TestData() [Theory] [MemberData(nameof(ToChar_InvalidObject_TestData))] - [MemberData(nameof(InvalidBool_TestData))] public void ToChar_InvalidObject_ThrowsInvalidCastException(object value) { Assert.Throws(() => Conversions.ToChar(value)); } + [Theory] + [MemberData(nameof(InvalidBool_TestData))] + public void ToChar_InvalidBool_ThrowsInvalidOperationException(object value) + { + Assert.Throws(() => Conversions.ToChar(value)); + } + private static object s_floatEnum; public static object FloatEnum @@ -2493,6 +2682,7 @@ public static object UIntPtrEnum return s_uintPtrEnum; } } + private static void AssertEqual(object expected, object actual) { if (expected is double expectedDouble && actual is double actualDouble) diff --git a/src/Microsoft.VisualBasic/tests/IConvertibleWrapper.cs b/src/Microsoft.VisualBasic/tests/IConvertibleWrapper.cs new file mode 100644 index 000000000000..f6dc4a5ed2dd --- /dev/null +++ b/src/Microsoft.VisualBasic/tests/IConvertibleWrapper.cs @@ -0,0 +1,52 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; + +namespace Microsoft.VisualBasic.Tests +{ + public class ConvertibleWrapper : IConvertible + { + public IConvertible Value { get; } + + public ConvertibleWrapper(IConvertible value) + { + Value = value; + } + + public TypeCode GetTypeCode() => Value.GetTypeCode(); + + public bool ToBoolean(IFormatProvider provider) => Value.ToBoolean(provider); + + public byte ToByte(IFormatProvider provider) => Value.ToByte(provider); + + public char ToChar(IFormatProvider provider) => Value.ToChar(provider); + + public DateTime ToDateTime(IFormatProvider provider) => Value.ToDateTime(provider); + + public decimal ToDecimal(IFormatProvider provider) => Value.ToDecimal(provider); + + public double ToDouble(IFormatProvider provider) => Value.ToDouble(provider); + + public short ToInt16(IFormatProvider provider) => Value.ToInt16(provider); + + public int ToInt32(IFormatProvider provider) => Value.ToInt32(provider); + + public long ToInt64(IFormatProvider provider) => Value.ToInt64(provider); + + public sbyte ToSByte(IFormatProvider provider) => Value.ToSByte(provider); + + public float ToSingle(IFormatProvider provider) => Value.ToSingle(provider); + + public string ToString(IFormatProvider provider) => Value.ToString(provider); + + public object ToType(Type conversionType, IFormatProvider provider) => Value.ToType(conversionType, provider); + + public ushort ToUInt16(IFormatProvider provider) => Value.ToUInt16(provider); + + public uint ToUInt32(IFormatProvider provider) => Value.ToUInt32(provider); + + public ulong ToUInt64(IFormatProvider provider) => Value.ToUInt64(provider); + } +} diff --git a/src/Microsoft.VisualBasic/tests/Microsoft.VisualBasic.Tests.csproj b/src/Microsoft.VisualBasic/tests/Microsoft.VisualBasic.Tests.csproj index e57d353bfcc2..40a69a1ed233 100644 --- a/src/Microsoft.VisualBasic/tests/Microsoft.VisualBasic.Tests.csproj +++ b/src/Microsoft.VisualBasic/tests/Microsoft.VisualBasic.Tests.csproj @@ -25,6 +25,7 @@ +