为什么';我的C#编译器(VisualStudio)是否允许我使用try块来执行此操作?
我在开发过程中有很多场景,我想做一些事情,比如为什么';我的C#编译器(VisualStudio)是否允许我使用try块来执行此操作?,c#,visual-studio-2013,C#,Visual Studio 2013,我在开发过程中有很多场景,我想做一些事情,比如 try { long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs); } catch ( Exception e ) { throw e; } result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
try
{
long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs);
}
catch ( Exception e )
{
throw e;
}
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
// ...
return presult;
说
当前上下文中不存在名称“presult”
如果它是智能的,它会理解presult
要么在try
块中初始化,要么在使用presult
之前退出该过程
可能的解决办法(没有一个是好的):
长预设代码>就在try
语句之前。这使编译器非常生气,因为它错误地认为有可能返回未初始化的变量
long presult=default(long)
初始化它。这是可行的,但这是一种糟糕的做法,因为阅读代码的人不知道将其初始化为默认值是否可以解决1中描述的问题。或者是因为值presult
,因为设置为默认值long
在程序上下文中具有某种实际意义long初始化它?presult=null
。这在语义上更好,因为很明显它的意思是“presult在这一点上没有任何价值”,而在2。读者必须明白预设有一个毫无意义的价值。这里的问题是,null
ify一个值不仅需要额外的内存,但随后我必须更改函数EvalInner
以返回long?
,这导致一系列需要将更多long
s更改为long?
s,我的程序最终被null
指定的变量打乱;这是一个完全混乱的问号哈哈try
{
long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs);
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
// ...
return presult;
}
catch ( Exception e )
{
//Do some useful logging
throw; //Don't lose stacktrace!
}
试试看
{
long presult=EvalInner(eqtn,新元组(++begidx,curidx-1),eqtnArgs);
结果=evalNewResult(结果、lastop、presult、ref negateNextNum、ref negateNextOp);
// ...
回归预设;
}
捕获(例外e)
{
//做一些有用的日志记录
抛出;//不要丢失stacktrace!
}
我不理解你的问题。调用evalNewResult
时,编译器无法知道presult
的值,因此需要在try块之外声明它。这是C#和许多其他语言中作用域的一般规则
解决方案是在try块之前声明并初始化它。问题是“在发生异常时,预设的值应该是什么”。编译器无法自行提出此问题。请检查此问题以获得更多启示
编译器的工作是生成代码,管理由该程序操作的数据的存储。有很多不同的生成代码来管理内存的方法,但随着时间的推移,两种基本技术已经根深蒂固
第一种是要有某种“长寿命”存储区域,其中存储中每个字节的“生存期”——即它与某个程序变量有效关联的时间段——不能轻易提前预测。编译器生成对“堆管理器”的调用,该“堆管理器”知道如何在需要时动态分配存储,并在不再需要时回收存储
第二种是具有某种“短寿命”存储区域,其中存储中每个字节的生存期是众所周知的,特别是存储的生存期遵循“嵌套”模式。也就是说,短周期变量中最长周期变量的分配与随后的短周期变量的分配严格重叠
局部变量遵循后一种模式;当一个方法被输入时,它的局部变量就活跃了。当该方法调用另一个方法时,新方法的局部变量会激活。在第一个方法的局部变量死之前,它们就死了。可以提前计算出与局部变量相关的存储的生命周期的开始和结束的相对顺序
由于这个原因,局部变量通常被生成为“堆栈”数据结构上的存储,因为堆栈具有这样一个属性,即推到堆栈上的第一个对象将是最后弹出的对象
所以整体局部变量的寿命很短,通常存储在堆栈中,为什么堆栈比其他堆栈更有效呢。有关为什么堆叠的更多信息,我将逐一介绍您的观点:
long
、int
、short
等这样的值类型必须有一个值,这是一种不错的做法。如果要将它们表示为没有值,请使用这些类型的可空版本(即long?presult=n)
try
{
long presult = EvalInner(eqtn,new Tuple<int, int>(++begidx,curidx-1),eqtnArgs);
result = evalNewResult(result,lastop,presult,ref negateNextNum,ref negateNextOp);
// ...
return presult;
}
catch ( Exception e )
{
//Do some useful logging
throw; //Don't lose stacktrace!
}
using System;
namespace app1
{
class Program
{
static void Main(string[] args)
{
Presult();
}
private static long Presult()
{
long presult;
try
{
object eqtn = null;
char begidx = '\0';
int curidx = 0;
object eqtnArgs = null;
presult = EvalInner(eqtn, new Tuple<int, int>(++begidx, curidx - 1), eqtnArgs);
}
catch (Exception e)
{
throw e;
}
int result = 0;
object lastop = null;
object negateNextNum = null;
object negateNextOp = null;
result = evalNewResult(result, lastop, presult, ref negateNextNum, ref negateNextOp);
// ...
return presult;
}
private static int evalNewResult(int result, object lastop, long presult, ref object negateNextNum, ref object negateNextOp)
{
return 0;
}
private static long EvalInner(object eqtn, Tuple<int, int> tuple, object eqtnArgs)
{
return 0;
}
}
}