The explicit implementations of IList.Add/Insert/Set methods catch
InvalidCastException for casting input argument to type T to throw
an ArgumentException. The issue here is they put the core collection
modification operation in the try block, which could be overridden
by sub-classes and produce an InvalidCastException from user logic,
even the argument passed to IList.Add/Insert/Set is valid.
To fix the issue, we just need to move the collection modification
outside the try block, and leave the casting in try block only. In
this way, we'll get an ArgumentException when the argument type is
invalid, but propagate the InvalidCastException thrown from user
code as it should be.
dotnet/corefxdotnet/coreclr#39919
Commit migrated from https://github.com/dotnet/coreclr/commit/
322529912639e9ba0ea2306181b9f6034fdee5ae
{
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+ T item = default(T)!;
+
try
{
- this[index] = (T)value!;
+ item = (T)value!;
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
}
+
+ this[index] = item;
}
}
}
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+ T item = default(T)!;
+
try
{
- Add((T)value!);
+ item = (T)value!;
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
}
+ Add(item);
+
return this.Count - 1;
}
}
ThrowHelper.IfNullAndNullsAreIllegalThenThrow<T>(value, ExceptionArgument.value);
+ T item = default(T)!;
+
try
{
- Insert(index, (T)value!);
+ item = (T)value!;
}
catch (InvalidCastException)
{
ThrowHelper.ThrowWrongValueTypeArgumentException(value, typeof(T));
}
+
+ Insert(index, item);
}
void IList.Remove(object? value)