只是偶然发现了一个简单的错误,它提示了一个有趣的问题.环境:VS 2010,NET.4,C#.从SQL sproc获取返回值会产生"指定的强制转换无效"异常:
cm.Parameters.Add( "@si", SqlDbType.SmallInt ).Direction= ParameterDirection.ReturnValue;
..
cm.ExecuteNonQuery( );
short siRetVal= (short) cm.Parameters[0].Value; // exception here
Run Code Online (Sandbox Code Playgroud)
由于代码在调试模式下运行并在该行中断,我输入了立即窗口:
?(short) cm.Parameters[0].Value
Run Code Online (Sandbox Code Playgroud)
结果是:
Cannot unbox 'cm.Parameters[0].Value' as a 'short'
Run Code Online (Sandbox Code Playgroud)

好吧,SQL sproc返回一个32位int(不是short我最初想到的16位),这解释了异常.应该为此参数使用适当的宽度 - 没有问题.
但任何人都可以解释为什么错误的根本原因仅在立即窗口中报告?Exception Helper中没有公开任何细节,内部异常为空.知道确切原因不是有益的吗?我认为它会使错误分析更简单,不是吗?
编辑:添加截图; 堆栈跟踪似乎没有暗示任何ADO.NET代码(我没想到).更重要的是,如果我将ret-value参数"声明"保留为SmallInt,但提供一个适当宽度的变量(或如图所示),适应一个int,一切正常!我很确定这与ADO/SQL没有任何关系.
我相信@HansPassant揭示了这里发生的事情的真实本质,我倾向于接受这个作为答案.尽管发现托管代码甚至无法向我提供有关执行状态的准确详细信息(例如,哪个引用实际上为null - 如上所述,或者在此无效转换的情况下),这有点令人失望.
我有一个数据库查询,它将返回NULL或布尔(位)值.
我希望将此值存储Nullable<bool>在C#中的类型变量中.
我似乎无法找到一个可接受的explict强制转换和转换组合,以简单的方式执行此操作,而不会抛出异常.
它可以用一条可读行完成吗?
编辑:代码请求
private Nullable<bool> IsRestricted;
...//data access
IsRestricted = (bool?)DataBinder.GetPropertyValue(dataObj, "IsRestricted");
Run Code Online (Sandbox Code Playgroud)
也许
IsRestricted = (bool?)(bool)DataBinder.GetPropertyValue(dataObj, "IsRestricted");
Run Code Online (Sandbox Code Playgroud) 所以我要通过旧代码(2.0),我遇到了这个:
object isReviewingValue = ViewState["IsReviewing"];
if (isReviewingValue is bool)
{
return (bool)isReviewingValue;
}
Run Code Online (Sandbox Code Playgroud)
我的第一个想法是给我们"as"关键字,以避免不必要的
(bool)isReviewingValue;
Run Code Online (Sandbox Code Playgroud)
但"as"仅适用于非值类型.没问题,我就这样做了:
bool? isReviewingValue= ViewState["IsReviewing"] as bool?;
if (isReviewingValue.HasValue)
{
return isReviewingValue.Value;
}
Run Code Online (Sandbox Code Playgroud)
问题是:除了看起来更具可读性之外,这实际上更好吗?
编辑:
public Stopwatch AsRun()
{
Stopwatch watch = new Stopwatch();
watch.Start();
for (Int32 loopCounter = 0; loopCounter < 10000; loopCounter++)
{
Object value = true;
Boolean? test = value as Boolean?;
if (test.HasValue)
{
Boolean something = test.Value;
}
}
watch.Stop();
return watch;
}
public Stopwatch ObjectIsRun()
{
Stopwatch watch = new …Run Code Online (Sandbox Code Playgroud) 考虑以下代码:
static void FillUsingAsNullable()
{
int?[] arr = new int?[1 << 24];
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < arr.Length; ++i)
arr[i] = GetObject() as int?;
Console.WriteLine("{0:N0}", sw.ElapsedTicks);
}
static void FillUsingOwnCode()
{
int?[] arr = new int?[1 << 24];
var sw = System.Diagnostics.Stopwatch.StartNew();
for (int i = 0; i < arr.Length; ++i)
{
object temporary = GetObject();
arr[i] = temporary is int ? (int?)temporary : null;
}
Console.WriteLine("{0:N0}", sw.ElapsedTicks);
}
static object GetObject()
{
//Uncomment …Run Code Online (Sandbox Code Playgroud) 当我偶然发现“空类型”一章中的一段时,我正在阅读乔恩·斯基特的“ C#in depth”第二版:
令人惊讶的性能陷阱我一直以为执行一次检查要快于两次检查,但事实并非如此-至少对于我测试过的.NET版本而言。在编写一个快速基准测试时,使用“ is”对“ object []”类型的数组中的所有整数进行求和,其中只有三分之一的值实际上是装箱的整数,然后强制转换最终比使用“” 快20倍作为'运算符。
乍一看,我认为编译器可能足够聪明,可以优化使用'is'+ cast时发生的双重类型检查,但事实并非如此。用/ OPTIMIZE标志打开的用32位编译器编译的.NET 4.0代码仍然导致两个MSIL'isinst'调用。
对于在直观上应该相反的情况下,如此巨大的性能差异可能有何解释?
几个月前我参加了一个研讨会,发言人声明自从.NET 1.1以来,装箱或拆箱操作的总成本已经降低.我查看了我的(差)注释,无法确定此语句是否引用了box和unbox指令,或者引用了类(即泛型类型),使得装箱/拆箱不太可能发生.
.NET 1.1和.NET 4.0之间的CLR拳击相关指令是否有性能改进,如果是这样,我在哪里可以找到有关显示收益的测量信息?
考虑这段代码:
private static void Main(string[] args)
{
short age = 123;
object ageObject = age;
//var intAge = (int)ageObject;//Specified cast is not valid.
int newAge= (short)intAge;
Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)
我必须为 object 分配一个短值,然后再次强制转换为 int ,但是当我尝试这样做时:var intAge = (int)ageObject;我得到:指定的强制转换无效。我不知道为什么?
在谷歌搜索后我发现应该转换为short并分配给int:int newAge= (short)intAge;
为什么我们应该转换为short并分配给int?
为什么编译器有这种行为?
编写您知道可能失败的代码并忽略异常,是不是风格和/或性能不好?例如(在C#中):
long l = 1;
try {
l = (long)castObject;
} catch(InvalidCastException e) { }
Run Code Online (Sandbox Code Playgroud)
在这种情况下,程序员并不特别关心是否InvalidCastException抛出了一个.
我完全知道为什么 as不能用于值类型.但是,我所知道的唯一替代品是:
if (!(obj is MyValueType)) { // Type check #1
// Exception or whatnot
}
var myValueType = (MyValueType)obj; // Type check #2
Run Code Online (Sandbox Code Playgroud)
但是,此代码执行两次类型检查,这会产生性能成本,as而引用类型的成本相同.
我的问题:对于值类型,是否有更好的性能机制/语法?
我能想到的唯一单一类型检查机制是try/catch,但这当然具有自己的性能成本,我尽量避免基于异常的编程.
什么是更快
AnswerClass ansClass = obj as AnswerClass;
if(ansClass != null){
//use ansClass directly
}
Run Code Online (Sandbox Code Playgroud)
要么
if(obj is AnswerClass ){
AnswerClass ansClass = (AnswerClass) obj;
//use ansClass now
}
Run Code Online (Sandbox Code Playgroud)
在C#.net中.
我环顾四周但找不到任何可以解答的问题,这里有人知道吗?
我已编辑以更好地解释我的问题,它是比较'as'然后null检查,然后使用,'is'然后直接演员?
c# ×11
.net ×3
nullable ×2
performance ×2
.net-4.0 ×1
as-operator ×1
boxing ×1
casting ×1
clr ×1
unboxing ×1
value-type ×1