public void SetValue(SecsIndexType type, object value, UInt32 lb = 0) { switch (type) { case SecsIndexType.U1: case SecsIndexType.B: // Binary - often treated as a byte or byte array case SecsIndexType.Boolean: if (value is byte[] byteArray) { if (type == SecsIndexType.Boolean && byteArray.Length != 1) { throw new ArgumentException($"For Boolean type, byte array length must be 1, but got {byteArray.Length}. Value: {BitConverter.ToString(byteArray).Replace("-", "")}", nameof(value)); } if (type == SecsIndexType.Boolean && !(byteArray[0] == 0 || byteArray[0] == 1)) { throw new ArgumentOutOfRangeException(nameof(value), $"Boolean byte value '{byteArray[0]}' is not 0 or 1."); } if (type == SecsIndexType.U1) Set_U1(byteArray, lb); else if (type == SecsIndexType.B) Set_B(byteArray, lb); else if (type == SecsIndexType.Boolean) Set_Boolean(byteArray, lb); } else if (value is byte singleByte) { if (type == SecsIndexType.Boolean && !(singleByte == 0 || singleByte == 1)) { throw new ArgumentOutOfRangeException(nameof(value), $"Boolean byte value '{singleByte}' is not 0 or 1."); } byte[] vbytes = new byte[1] { singleByte }; if (type == SecsIndexType.U1) Set_U1(vbytes, lb); else if (type == SecsIndexType.B) Set_B(vbytes, lb); else if (type == SecsIndexType.Boolean) Set_Boolean(vbytes, lb); } else { byte byteToSet = 0; // Initialize to prevent CS0165 bool conversionOk = false; if (value is int i) { if (i >= 0 && i <= 255) { byteToSet = (byte)i; conversionOk = true; } else { throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of byte range (0-255) for SECS type {type}."); } } else if (value is long l) { if (l >= 0 && l <= 255) { byteToSet = (byte)l; conversionOk = true; } else { throw new ArgumentOutOfRangeException(nameof(value), $"Long value '{l}' is out of byte range (0-255) for SECS type {type}."); } } else if (value is uint ui) { if (ui <= 255) { byteToSet = (byte)ui; conversionOk = true; } else { throw new ArgumentOutOfRangeException(nameof(value), $"UInt value '{ui}' is out of byte range (0-255) for SECS type {type}."); } } else if (value is string s) { // Consider NumberStyles and CultureInfo for robust parsing if (byte.TryParse(s, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture, out byteToSet)) { conversionOk = true; } else { throw new ArgumentException($"String value '{s}' cannot be converted to byte for SECS type {type}.", nameof(value)); } } else if (type == SecsIndexType.Boolean && value is bool boolVal) { byteToSet = Convert.ToByte(boolVal); conversionOk = true; } if (conversionOk) { if (type == SecsIndexType.Boolean && !(byteToSet == 0 || byteToSet == 1)) { throw new ArgumentOutOfRangeException(nameof(value), $"Converted Boolean value '{byteToSet}' is not 0 or 1."); } byte[] vbytes = new byte[1] { byteToSet }; if (type == SecsIndexType.U1) Set_U1(vbytes, lb); else if (type == SecsIndexType.B) Set_B(vbytes, lb); else if (type == SecsIndexType.Boolean) Set_Boolean(vbytes, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted to byte for SECS type {type}.", nameof(value)); } } break; case SecsIndexType.U2: if (value is ushort[] valUshortArray) { Set_U2(valUshortArray, lb); } else if (value is short[] valShortArray) { Set_U2(Array.ConvertAll(valShortArray, Convert.ToUInt16), lb); } else if (value is int[] valIntArrayForU2) { Set_U2(Array.ConvertAll(valIntArrayForU2, i => { if (i < ushort.MinValue || i > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of UInt16 range for SECS type {type}."); return Convert.ToUInt16(i); }), lb); } else if (value is ushort valUshort) { Set_U2(new ushort[] { valUshort }, lb); } else if (value is short valShort) { Set_U2(new ushort[] { Convert.ToUInt16(valShort) }, lb); } // Add range check if necessary else if (value is int valIntForU2) { if (valIntForU2 < ushort.MinValue || valIntForU2 > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForU2}' is out of UInt16 range for SECS type {type}."); Set_U2(new ushort[] { Convert.ToUInt16(valIntForU2) }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.U4: if (value is uint[] valUintArray) { Set_U4(valUintArray, lb); } else if (value is int[] valIntArrayForU4) { Set_U4(Array.ConvertAll(valIntArrayForU4, i => { if (i < 0 && (long)i + uint.MaxValue + 1 != 0) { /* check for negative numbers that cannot be cast to uint without data loss, simple i < 0 is not enough for int.MinValue */ } // A direct cast (uint)i for negative numbers will wrap around. // Depending on desired behavior, either throw or convert carefully. // For simplicity, let's assume positive or use Convert.ToUInt32 which throws for negatives. return Convert.ToUInt32(i); // This will throw OverflowException for negative i }), lb); } else if (value is uint valUint) { Set_U4(new uint[] { valUint }, lb); } else if (value is int valIntForU4) { Set_U4(new uint[] { Convert.ToUInt32(valIntForU4) }, lb); } // Will throw for negative else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.U8: if (value is ulong[] valUlongArray) { Set_U8(valUlongArray, lb); } else if (value is long[] valLongArrayForU8) { Set_U8(Array.ConvertAll(valLongArrayForU8, Convert.ToUInt64), lb); } // Throws for negative else if (value is ulong valUlong) { Set_U8(new ulong[] { valUlong }, lb); } else if (value is long valLongForU8) { Set_U8(new ulong[] { Convert.ToUInt64(valLongForU8) }, lb); } // Throws for negative else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.I1: if (value is sbyte[] valSbyteArray) { Set_I1(valSbyteArray, lb); } else if (value is byte[] valByteArrayForI1) { Set_I1(Array.ConvertAll(valByteArrayForI1, Convert.ToSByte), lb); } // Throws if > 127 else if (value is int[] valIntArrayForI1) { Set_I1(Array.ConvertAll(valIntArrayForI1, i => { if (i < SByte.MinValue || i > SByte.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of SByte range for SECS type {type}."); return Convert.ToSByte(i); }), lb); } else if (value is sbyte valSbyte) { Set_I1(new sbyte[] { valSbyte }, lb); } else if (value is byte valByteForI1) { Set_I1(new sbyte[] { Convert.ToSByte(valByteForI1) }, lb); } // Throws if > 127 else if (value is int valIntForI1) { if (valIntForI1 < SByte.MinValue || valIntForI1 > SByte.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForI1}' is out of SByte range for SECS type {type}."); Set_I1(new sbyte[] { Convert.ToSByte(valIntForI1) }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.I2: if (value is short[] valShortArrayForI2) { Set_I2(valShortArrayForI2, lb); } else if (value is int[] valIntArrayForI2) { Set_I2(Array.ConvertAll(valIntArrayForI2, i => { if (i < short.MinValue || i > short.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of Int16 range for SECS type {type}."); return Convert.ToInt16(i); }), lb); } else if (value is short valShortForI2) { Set_I2(new short[] { valShortForI2 }, lb); } else if (value is int valIntForI2) { if (valIntForI2 < short.MinValue || valIntForI2 > short.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{valIntForI2}' is out of Int16 range for SECS type {type}."); Set_I2(new short[] { Convert.ToInt16(valIntForI2) }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.I4: if (value is int[] valIntArrayForI4) { Set_I4(valIntArrayForI4, lb); } else if (value is int valIntForI4) { Set_I4(new int[] { valIntForI4 }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.I8: if (value is long[] valLongArrayForI8) { Set_I8(valLongArrayForI8, lb); } else if (value is long valLongForI8) { Set_I8(new long[] { valLongForI8 }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.F4: if (value is float[] valFloatArray) { Set_F4(valFloatArray, lb); } else if (value is double[] valDblArrayForF4) { Set_F4(Array.ConvertAll(valDblArrayForF4, Convert.ToSingle), lb); } else if (value is float valFloat) { Set_F4(new float[] { valFloat }, lb); } else if (value is double valDblForF4) { Set_F4(new float[] { Convert.ToSingle(valDblForF4) }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.F8: if (value is double[] valDblArrayForF8) { Set_F8(valDblArrayForF8, lb); } else if (value is float[] valFltArrayForF8) { Set_F8(Array.ConvertAll(valFltArrayForF8, f => (double)f), lb); } else if (value is double valDblForF8) { Set_F8(new double[] { valDblForF8 }, lb); } else if (value is float valFltForF8) { Set_F8(new double[] { (double)valFltForF8 }, lb); } else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; case SecsIndexType.List: if (value is int listLength) { if (listLength < 0) throw new ArgumentOutOfRangeException(nameof(value), $"List length '{listLength}' cannot be negative for SECS type {type}."); Set_List(listLength, lb); } else if (value is uint listLengthUint) { // Allow uint for length too if (listLengthUint > int.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"List length '{listLengthUint}' is too large for SECS type {type}."); Set_List((int)listLengthUint, lb); } else { throw new ArgumentException($"List length value '{value}' (type: {value?.GetType().FullName}) must be a non-negative integer for SECS type {type}.", nameof(value)); } break; case SecsIndexType.A: case SecsIndexType.Ax: case SecsIndexType.J: case SecsIndexType.Jx: string strValue = value?.ToString() ?? string.Empty; // 將 null 轉換為空字串 if (type == SecsIndexType.A) Set_A(strValue, lb); else if (type == SecsIndexType.Ax) Set_Ax(strValue, lb); else if (type == SecsIndexType.J) Set_J(strValue, lb); else if (type == SecsIndexType.Jx) Set_Jx(strValue, lb); break; case SecsIndexType.A2: // Array of UInt16 if (value is ushort[] valUshortArrayForA2) { Set_A2(valUshortArrayForA2, lb); } else if (value is int[] valIntArrayForA2) { Set_A2(Array.ConvertAll(valIntArrayForA2, i => { if (i < ushort.MinValue || i > ushort.MaxValue) throw new ArgumentOutOfRangeException(nameof(value), $"Integer value '{i}' is out of UInt16 range for SECS type {type}."); return Convert.ToUInt16(i); }), lb); } // Potentially convert string to ushort[] if A2 represents wide characters else { throw new ArgumentException($"Value '{value}' (type: {value?.GetType().FullName}) cannot be converted for SECS type {type}.", nameof(value)); } break; default: throw new NotSupportedException($"SECS type {type} is not currently supported in SetValue operation."); } }