我有一个定义为List<int> myIntList = new List<int>();
的整数列表像往常一样,我将使用myIntList.Add()
方法为列表添加值。我面临的问题是列表中的值是动态的(某些计算结果),可能超过整数可以容纳的最大值。
考虑以下情况:
int x = int.MaxValue;
myIntList.Add(x + 1);
这会将-2147483648
添加到列表中,而不是抛出异常。我需要在这里抛出异常。我知道myIntList.Add(checked(x + 1));
可以完美地完成这项工作,或者我甚至可以在checked{}
中包含myIntList.Add(),如下所示:
checked
{
myIntList.Add(12);
myIntList.Add(int.MaxValue);
myIntList.Add(x + 1);
}
这是我的问题有什么替代方案吗?我可以定义已检查整数的列表吗?如何在列表中添加的值超出限制的情况下创建一个引发异常的列表?
更新
谢谢大家的回复,大多数人建议在将它们添加到列表之前检查整数(如果它超出边界则抛出异常)。这与我通过给定的片段checked{// add elements }
完成的操作相同,它会在没有任何复杂条件检查的情况下抛出异常。
答案 0 :(得分:8)
您正在错误的级别解决问题。首先,你的计算 - 它返回某种类型的值 - int
,long
等。不应该检查溢出吗?它没有溢出,但返回long
,例如?
如果在添加到容器时仍然应该这样做,您可以创建如下的检查列表:
class CheckedList : List<int>
{
public void Add(long x)
{
if (int.MaxValue < x || int.MinValue > x) throw new ArgumentOutOfRangeException("Invalid");
var i = (int) x;
base.Add(i);
}
}
答案 1 :(得分:3)
假设你想要这样的行为:
List<CheckedInt> myIntList = new List<CheckedInt>();
CheckedInt check1 = int.MaxValue;
CheckedInt check2 = 1;
myIntList.Add(check1 + check2); //exception occurs!
最干净的方法之一(这样可以保留x + y
等操作代码,但同时能够throwing exception
)将是使用重载运算符 定义您自己的CheckedInt
(基于int
)。
结构
CheckedInt
struct
将是这样的:
public struct CheckedInt {
private int Value { get; set; }
public CheckedInt(int value)
: this() {
Value = value;
}
public static implicit operator CheckedInt(int me) {
return new CheckedInt(me);
}
public static CheckedInt operator +(CheckedInt lhs, CheckedInt rhs) {
double testResult = (double)lhs.Value + (double)rhs.Value;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs.Value + rhs.Value); //note that direct lhs+rhs will cause StackOverflow
}
public static CheckedInt operator -(CheckedInt lhs, CheckedInt rhs) {
double testResult = (double)lhs.Value - (double)rhs.Value;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs.Value - rhs.Value); //note that direct lhs-rhs will cause StackOverflow
}
public static CheckedInt operator *(CheckedInt lhs, CheckedInt rhs) {
double testResult = (double)lhs.Value * (double)rhs.Value;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs.Value * rhs.Value); //note that direct lhs*rhs will cause StackOverflow
}
public static CheckedInt operator /(CheckedInt lhs, CheckedInt rhs) {
double testResult = (double)lhs.Value / (double)rhs.Value;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs.Value / rhs.Value); //note that direct lhs-rhs will cause StackOverflow
}
//Add any other overload that you want
public override string ToString() { //example
return Value.ToString();
}
public bool Equals(CheckedInt otherInt) { //example
return Value == otherInt.Value;
}
}
例外
你也可以定义自己的例外。
public class MyCheckedIntException : Exception {
public MyCheckedIntException() {
//put something
}
public MyCheckedIntException(string message) : base(message) {
//put something
}
public MyCheckedIntException(string message, Exception inner) : base(message, inner) {
//put something
}
现在,你有List
CheckedInt
个真实的人。
使用
只需像这样使用它:
CheckedInt check1 = int.MaxValue;
CheckedInt check2 = 1;
这句话:
List<CheckedInt> myIntList = new List<CheckedInt>();
myIntList.Add(check1 + check2); //exception!
将为您抛出异常MyCheckedIntException
。
扩展,清洁外观
如果你想像其中任何一个一样使用它:
myIntList.Add(check1 + 1); //note that `1` is not type of checked integer
myIntList.Add(1 + check1); //note that `1` is not type of checked integer
然后只需将overloading
添加到operator overloads
:
public static CheckedInt operator +(CheckedInt lhs, int rhs) { //note the type of rhs
double testResult = (double)lhs.Value + (double)rhs;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs.Value + rhs); //note that direct lhs+rhs will cause StackOverflow
}
public static CheckedInt operator +(int lhs, CheckedInt rhs) { //not the type of lhs
double testResult = (double)lhs + (double)rhs.Value;
if (testResult > int.MaxValue || testResult < int.MinValue)
throw new MyCheckedIntException();
return new CheckedInt(lhs + rhs.Value); //note that direct lhs+rhs will cause StackOverflow
}
您也可以为所有其他运营商做同样的事情。
答案 2 :(得分:1)
您无法检查该总和的结果是否超出范围,因为如果您只有结果,则您没有所有必需的数据。如果你的问题确实存在溢出int
,你有几个选择:
您可以为列表创建扩展方法
2a)创建与选项1中相同的Add
方法。
2b)创建方法,在其中添加数字并决定(你必须知道你想对这些数字做什么操作,但是将注释改为long等等应该没有任何问题):
public static void Add(this List<int> list, int value, int otherValue)
{
if ((long)value + otherValue > int.MaxValue ||
(long)value + otherValue < int.MinValue)
{
throw new ArgumentOutOfRangeException("Integer overflow");
}
else
{
list.Add(value + otherValue);
}
}
我认为您可以创建一些其他示例,但没有太大区别。
然而,重要的是要注意,使用checked
关键字(从我尝试过的)始终是最快的解决方案。实际上它几乎和没有检查的简单插入一样快,所以如果没有严重的理由不使用checked
关键字,我必须推荐它。
答案 3 :(得分:1)
在添加之前,我会(ref):
Int.TryParse(string,int)
因此,如果因为&gt;而失败int.MaxValue或&lt; Int.MinValue,它将返回false,因此您可以相应地处理它。
希望这有帮助
答案 4 :(得分:1)
只需通过解析并将值转换为更大的类型(例如long:
)即可List<int> myIntList = new List<int>();
int x = int.MaxValue;
myIntList.Add(int.Parse(((long)x + 1).ToString()));
它会抛出System.OverflowException。
myIntList.Add(int.Parse(((long)x - 1).ToString()));
否则将添加整数值。
答案 5 :(得分:1)
有一件事需要考虑。你在这里的实际意图是什么?我的意思是:如果您不想添加导致溢出的结果,为什么在实际尝试将它们添加到列表时检查它们?你怎么处理导致溢出的结果?你把它们添加到其他列表中吗?或者你忽略了它们?
我要做的是在实际调用List.Add()
之前检查溢出。这样,您就可以更好地控制数据流。您可以忽略,记录,替换等溢出的数据。
只需要考虑一些事情。
答案 6 :(得分:1)
处理它的两种方法:
checked/unchecked
包裹您的代码(正如您现在所做的那样)答案 7 :(得分:1)
这是我的问题这有什么替代方案吗?我可以定义一个 已检查整数列表?如何制作一个抛出的列表 添加到列表中的值超出的情况下的异常 限制?
在传递给List之前计算中发生溢出,因此List类不可能检测到这种溢出。溢出这个词在这里用得最严格。
替代方案基于您已经知道的内容,即使用checked
上下文。您可以使用编译选项/checked,这可能会减轻您使用关键字的麻烦。请注意,调用代码(不是List
代码)需要使用此选项进行编译。
答案 8 :(得分:1)
简短的回答是:不,你不能。
还有其他&#34;变通办法&#34;在其他答案中并没有完全符合您的要求,但这里有基本的解释,说明为什么您不能做您想做的事情:
编译时,代码基本上会分解为:
int x = int.MaxValue;
int temp = x + 1;
list.Add(temp);
编译器只是帮助您保存击键,而不是强制您为每个子表达式创建命名临时变量。因为必须创建这些临时变量。
要理解为什么{<1}}必须在调用x + 1
方法之前计算,您需要了解CPU如何执行代码,一些基本程序集和一些编译概念。所有这些都超出了这个问题的范围 - 如果你想了解更多信息,可以提出一个新问题。
答案 9 :(得分:0)
尝试引入IntWrapper
类,它负责添加两个整数。
public static class IntWrapper
{
public static Int32 Add(this Int32 left, Int32 right)
{
if ((Int64)left + (Int64)right > (Int64)Int32.MaxValue)
throw new ArgumentOutOfRangeException();
return left + right;
}
}
使用Add
方法添加两个整数。
答案 10 :(得分:-3)
在存储到列表中之前,您需要检测计算结果中的溢出。
假设x和y是正数:
if(x + y)&lt; x然后溢出