C#中的eval()函数

来源:百度文库 编辑:神马文学网 时间:2024/04/27 14:33:52
可以这样说,绝大多数的大型网站都会用到eval()函数,虽然一直在用,但其具体含义及使用还真没特别去注意过,搜索了下也没有什么明确的解释。

翻译过来的中文释义大体如下:

C# eval ()函数,是一个用来求值的解析表达式,支持布尔型(Boolean),二进制方式,算法,一元,所属,

成员(例如:object.property 对象属性),索引值(数组索引);条件函数,也支持变量赋值。

其有点在于:

无需运行时编译;

无需使用JScript.NET;

无需使用数据表。


英文如下:

C# eval function

parse expression and evaluate it. Supports Boolean, Bitwise, Arithmetic, Unary, Paren, Member (such as object.property ), Indexer (such as array[index]) and ConditionalIf(?:), also supports Variable assign.

you can use it like evaluate one statement C# source code.

not use runtime Compiler.

not use JScript.NET.

not use DataTable
是下面的缩写:
whole:
fir st-part last-part
fir st-part second-part last-part

 三、C#的预处理
预处理阶段是一个文本到文本的转换阶段,在预处理过程中,使能进行代码的条件包含和排除。
pp-un it:
pp-gro up opt
pp-gro up:
pp-gro up-part
pp-gro up pp-group-part
pp-gro up-part:
pp-tokensopt new-line
pp-de claration
pp-if -section
pp-con trol-line
pp-l ine-number
pp-tokens:
pp-token
pp-tokens pp-token
pp-token:
identifi er
keyword
literal
operator-or-punctuator
new-line:
The carriage return character (U+000D)
The line feed character (U+000A)
The carriage return character followed by a line feed character
The line separator character (U+2028)
The paragraph separator character (U+2029)

1、预处理声明
在预处理过程中,为了使用名称可以被定义和取消定义。#define 定义一个标识符。#undef “反定义”一个标识符,如果一个标识符在以前已经被定义了,那么它就变成了不明确的。如果一个标识符已经被定义了,它的语意就等同于true ;如果一个标识符没有意义,那么它的语意等同于false。
pp-de claration:
#define pp-identifier
#undef pp-identifier
来看看这个例子:
#define A
#undef B
class C
{
#if A
void F()
#else
void G()
#endif
#if B
void H()
#else
void I()
#endif
}
变为:
class C
{
void F()
void I()
}
如果有一个pp-unit, 声明就必须用pp- token 元素进行。换句话说,#define 和#undef 必须在文件中任何 “真正代码”前声明,否则在编译时会发生错误。因此,也许会像下面的例子一样散布#if 和#define:
#define A
#if A
#define B
#endif
namespace N
{
#if B
class Class1
#endif
}
因为#define 放在了真实代码后面,所以下面的例子是非法的:
#define A
namespace N
{
#define B
#if B
class Class1
#endif
}
一个#undef 也许会“反定义”一个没有定义的名称。下面的例子中定义了一个名字并且对它进行了两次反定义,第二个#undef 没有效果,但还是合法的。
#define A
#undef A
#undef A

2、 #if, #elif, #else, #endif
pp-if -section 用来对程序文本的一部件进行有条件地包括和排除。
pp-if -section:
pp-if -group pp-elif-groupsopt pp-else-groupopt pp-endif-line
pp-if -group:
#if pp-expression new-line pp -group opt
pp-e lif -groups
pp-e lif -group
pp-e lif -groups pp-elif-group
pp-e lif -group:
#elif pp-expression new-line group opt
pp-e lse-group:
#else new-line group opt
pp-end if -line
#endif new-line
举个例子:
#define Debug
class Class1
{
#if Debug
void Trace(string s)
#endif
}
变成:
class Class1
{
void Trace(string s)
}
如果这部分可以嵌套。
来看看例子:
#define Debug // Debugging on
#undef Trace // Tracing off
class PurchaseTransaction
{
void Commit() {
#if Debug
CheckConsistency();
#if Trace
WriteToLog(this.ToString());
#endif
#endif
CommitHelper();
}
}

3、预处理控制行
特性#error和#warning使得代码可以把警告和错误的条件报告给编译程序,来查出标准的编译时的警告和错误。

pp-con trol-line:
#error pp-message
#warning pp-message
pp-message:
pp-tokensopt
举个例子帮助大家理解
#warning Code review needed before check-in
#define DEBUG
#if DEBUG && RETAIL
#error A build can't be both debug and retail!
#endif
class Class1
{…}
这将总是产生警告(“Code review needed before check-in"),并且如果予处理修饰符DEBUG 和RETAIL 都被定义,还会产生错误。

4、 #line
#line 的特点使得开发者可以改变行的数量和编译器输出时使用的源文件名称,例如警告和错误。如果没有行指示符,那么行的数量和文件名称就会自动由编译器定义。#line指示符通常用于编程后的工具,它从其它文本输入产生C#源代码。
pp-l ine-number:
#line integer-literal
#line integer-literal string-literal
pp-in teger-literal:
decimal-digit
decimal-digits decimal-digit
pp-s tring-literal:
" pp-string-literal-characters "
pp -string-literal-characters:
pp-s tring-literal-character
pp-s tring-literal-characters pp-string-literal-character
pp-s tring-literal-character:
Any character except " (U+0022), and white-space

5、预处理标识符
预处理标识符使用和规则C#标识符文法相似的文法:
pp -identifi er:
pp-ava ilable-identifier
pp-ava ilable-identifi er:
A pp-identif ier-or-keyword that is not true or false
pp-id entif ier-or-keyword:
identifi er-start-character identif ier-part-characters opt
true 和false 符号不是合法的预定义指示符,所以不能用于#define 的定义和#undef 的反定义。

6、预处理表达式
操作符!, ==, !=, && 和||是允许的预定义表达式。在预定义表达式中,圆括号可以用来分组。
pp-expression:
pp-equality-expression
pp-pr imary-expression:
true
false
pp -identifi er
( pp-expression )

pp-unary-expression:
pp-pr imary-expression
! pp-unary-expression
pp-equality-expression:
pp-equality-expression == pp-logical-and-expression
pp-equality-expression != pp-logical-and-expression
pp-logical-and-expression:
pp-unary-expression
pp-logical-and-expression && pp-unary-expression
pp-logical-or-expression:
pp-logical-and-expression
pp-logical-or-expression || pp-logical-and-expression

7、与空白交互作用
条件编译标识符必须在一行的第一个非空白位置。
一个单行注释可以跟在条件编译指示符或pp-c ontrol-line 标识符后面。
例如:
#define Debug // Defined if the build is a debug build
对于pp-control-line 标识符,一行的剩余组成pp-message,独立于此行的注释。
看看例子:
#warning // TODO: Add a better warning
会有一个注释为"// TODO: Add a better warning"的警告。
一个多行注释的起始和结束可以不在同一行中,就像条件编译标识符。
就像这个例子:
/* This comment is illegal because it
ends on the same line*/ #define Debug
/* This is comment is illegal because it is on the same line */ #define
Retail
#define A /* This is comment is illegal because it is on the same line */
#define B /* This comment is illegal because it starts
on the same line */
结果将是编译时错误。
可以形成一个条件编译标识符的数据符号可能会隐含在注释中。
看看这个例子:
// This entire line is a commment. #define Debug
/* This text would be a cc directive but it is commented out:
#define Retail
*/
不包含任何条件编译标识符,然而完全由空白组成。
小知识:编译语言与解释语言的优缺点对比
1、运行效率:
编译语言需要编译一次,运行直接执行、不需要翻译,所以编译型语言的程序执行效率高。而解释语言则不同,解释型语言的程序不需要编译,省了道工序,解释性语言在运行程序的时候才翻译,比如解释型basic语言,专门有一个解释器能够直接执行basic程序,每个语句都是执行的时候才翻译。这样解释性语言每执行一次就要翻译一次,效率比较低。
  解释执行的语言因为解释器不需要直接同机器码打交道所以实现起来较为简单、而且便于在不同的平台上面移植,这一点从现在的编程语言解释执行的居多就能看出来,如 Visual Basic、Visual Foxpro、Power Builder、Java...等。编译执行的语言因为要直接同CPU 的指令集打交道,具有很强的指令依赖性和系统依赖性,但编译后的程序执行效率要比解释语言要高的多,象现在的 Visual C/C++、Delphi 等都是很好的编译语言。
2、代码安全性
对于解释语言与编译语言所编制出来的代码安全性上而言,可以说是各有优缺点。曾经在 Windows 下跟踪调式过 VB 程序的朋友一般都知道,程序代码 99% 的时间里都是在 VBRUNxx 里转来转去,根本看不出一个所以然来。 这是因为你跟踪的是 VB 的解释器,要从解释器中看出代码的目的是什么是相当困难的。但解释语言有一个致命的弱点,那就是解释语言的程序代码都是以伪码的方式存放的,一旦被人找到了伪码与源码之间的对应关系,就很容易做出一个反编译器出来,你的源程序等于被公开了一样。而编译语言因为直接把用户程序 编译成机器码,再经过优化程序的优化,很难从程序返回到你的源程序的状态, 但对于熟悉汇编语言的解密者来说,也很容易通过跟踪你的代码来确定某些代码的用途。

然而,我们会看到在对象上完成运算的方法有所不同。
object.member_function(arglist)是对一个对象“调用一个成员函数”。而在面向对象的用法中,也称之为“向一个对象发送消息”。这样,对于stash K,语句K.add(&i)“发送消息给K”,也就是说,“对自己add( )”。事实上,面向对象程序设计可以总结为一句话,“向对象发送消息”。需要做的所有事情就是创建一束对象并且给它们发送消息。当然,问题是勾画出我们的对象和消息是什么,但如果完成了这些,C++ 的实现就直截了当了。
一个结构的大小是它的所有成员大小的和。有时,当一个struct 被编译器处理时,会增加额外的字节以使得捆绑更整齐,这主要是为了提高执行效率。
另外,用sizeof可以计算出struct的内存大小。
下面我们来看看相应的例子:
//计算struct内存
#include
struct A1
{
int i[100];
};
struct A2
{
void x();
};
void main(void)
{
printf(“size of struct A is %d\n”, sizeof(A1);
printf(“size of struct B is %d\n”, sizeof(A2);
}
第一句printf会打印出200,而第二句则会打印出一个不确定的非零值。
因为这个声明这个在C中不合法,但是在C++中是合法的。

你可以拿这个对比一下C#的声明。看看有些什么不同呢?