QQ水浒真成贵铁路怎么得 真成贵铁路得法

[C#] as 和 is 运算符以及安全的类型强制转换讨论 | 小谢的小站
TearSnow Fan
我一句话都不说……
您当前位置 :
>> [C#] as 和 is 运算符以及安全的类型强制转换讨论
[C#] as 和 is 运算符以及安全的类型强制转换讨论
根据 MSDN 的说明:由于对象是多态的,因此基类类型的变量可以保存派生类型。若要访问派生类型的方法,需要将值强制转换回该派生类型。不过,在这些情况下,如果只尝试进行简单的强制转换,会导致引发 InvalidCastException 的风险。鉴于这个过程是不安全的,因此需要用 try - catch 语句块来进行保护,例如比较安全的代码方式应该如下所示:
// 有一object类型的待转换对象 objTest
GivenType value =
value = (GivenType) objT
catch( Exception e )
MessageBox.Show( e.Message );
但是如上的写法在C#中已经属于过时的写法,而且也属于比较低效的写法。但是类似的转换会经常发生,为了避免异常导致的低效和代码的不简洁,C# 提供 is 和 as 运算符来进行转换。可以使用这两个运算符来测试强制转换是否会成功,而没有引发异常的风险。
一、is 运算符
is 运算符检查对象是否与给定类型兼容。例如,if ( obj is MyObject ) 将检查对象 obj 是否为 MyObject 类型的一个实例,或者是从 MyObject 派生的一个类型的实例。
对于is表达式的结果应该这么看待:如果所提供的对象(表达式)非空,并且可以被强制转换为所提供的类型而不会引发异常,则is表达式的结果就为true,否则为false。
通常使用is表达式的情况是程序运行时才计算类型兼容性,如果已知表达式的值始终为true或者fale,将会导致编译时的警告。
(1)is运算符只考虑引用转换、装箱转换和拆箱转换,不考虑其他转换(包括用户定义的转换)。例如虽然 int 和 double 是类型兼容的,但是使用is运算符的结果却是false。
(2)不能重载is运算符。
(3)在is运算符左侧不允许使用匿名方法(Lambda表达式例外)。
二、as 运算符
as 运算符用于在兼容的引用类型之间执行类似于强制类型转换的操作。与强制类型转换不同的是,如果无法进行转换,as运算符将返回null而不是引发异常。
expression as type
expression is type ? (type) expression : (type) null
(1)as 运算符只能执行引用转换和装箱转换,不能执行拆箱转换(应使用is运算符判断配合强制类型装换来完成);
(2)as运算符也不能执行其他转换,如用户定义的转换(这类转换应该首先需要相应类型提供转换函数并使用强制转换表达式来完成,或者使用case语句等其他方法来执行)。
下面提供了上述情况不适用as运算符的替代方案:
2.1 不能使用 as 运算符进行拆箱转换
即 as 运算符不能将引用类型数据转换为值类型数据,如下写会出现编译错误:
object objTest = 11;
int intValue = objT
正确的写法是:使用is操作符,再加上显式的类型转换操作,就可以安全完成转换,例如:
object objTest = 11;
if ( objTest is int )
int intValue = (int) objT
2.2 不能使用 as 运算符完成用户定义的转换
要想使用户定义的转换操作能正确完成,需要在原类型中增加类型转换操作符函数,例如:
public class NewTypeOne
public static explicit operator NewTypeTwo( NewTypeOne objTypeOne )
//Convert object into new type
并使用如下强制类型转换(不能使用 is 运算符和 as 运算符):
NewTypeOne objTypeOne = new NewTypeOne();
NewTypeTwo newTestTwo = (NewTypeTwo)newTestO
2.3 对 as 运算符使用可空类型
允许使用 as 运算符完成基本数据类型(已知值类型)之间的转换,但是由于使用 as 运算符可能产生null值,应注意可能需要对 as 运算符使用 nullable 类型,否则同样可能抛出异常。
下面是摘自MSDN的代码:
void UseAsWithNullable(System.ValueType val)
int? j = val as int?;
if (j != null)
Console.WriteLine(j);
Console.WriteLine(&Could not convert & + val.ToString());
需要说明的是,上述代码中的 int? 或者 Nullable &int&是“可空类型”。Nullable &T& 结构支持只将一个值类型用作可空类型,因为引用类型本身就是可空的。
三、as 运算符和 is 运算符的效率比较
通常,as 运算符更高效一些,因为如果可以成功进行强制转换,它会实际返回强制转换值。而 is 运算符只返回一个布尔值,可能在表达式为true时,还需要进行显示的转换,就需要执行两次类型兼容检查,例如:
object o =&abc&;
if ( o is string) //执行第一次类型兼容性检查
string s = (string)o; //执行第二次类型兼容性检查,并转换
MessageBox.Show( &转换成功!& );
MessageBox.Show( &转换失败!& );
而使用as运算符,可以改写为:
object o =&abc&;
string s =//执行第一次类型兼容性检查,并返回结果
if (s != null)
MessageBox.Show(&转换成功!&);
MessageBox.Show(&转换失败!&);
对比两种方式,is 需要做两次对象的类型检查;而 as 需要做一次对象类型检查,再加一次null的检查,但是null检查的开销比对象类型检查少,因此相对来说,as的方法效率高些。当然,只是检测类型是否相符那么只用is就可以了,如果要进行类型转化可以直接用as。
四、类型转换总结
综上所述,那么在进行类型转换的时候,可以按照如下的方式进行选择。
Object --& 已知引用类型
使用 as 操作符来完成
Object --& 基本数据类型(拆箱)
先使用 is 操作符来进行判断,再用强制转换方式进行转换
用户定义类型之间转换
首先需要相应类型提供转换函数,再用强制转换方式进行转换
基本数据类型之间转换
最好使用.Net提供的Convert类所涉及的静态方法
其他类型转换相关:
1. 任何类型都可以转换为其基类类型,用隐式转换即可完成;
2. 任何类型转换为其派生类型时,必须进行显示转换。如:(类型名)对象名;
3. 使用 GetType方法可以取得任何对象实例的精确类型(注意区分Typeof运算符区分);
4. 基本数据类型是都是已知的值类型,可以使用 Convert 类实现类型转换;
5. 除了 string 以外的其他类型都有 Parse 方法,用于将字符串类型转换成对应的基本类型;
6. 值类型和引用类型的转换称为装箱(boxing)或拆箱(unboxing)。(根据MSDN编程指南:装箱是将值类型转换为object类型或由此值类型实现的任一接口类型的过程。当CLR对值类型进行装箱时,会将该值包装到System.Object内部,再将后者存储在托管堆上。取消装箱将从对象中提取值类型。)
参考资料:
1. 如何:使用 as 和 is 运算符安全地进行强制转换(C# 编程指南). MSDN.
2. as(C#参考). MSDN.
3. is(C#参考). MSDN.
4. C# 中 as 和 is 的用法.
5. C# as 与 is.
本文固定链接:
【上一篇】【下一篇】
您可能还会对这些文章感兴趣!
最新日志热评日志随机日志
官方微信扫一扫
日志总数:151 篇
评论总数:379 篇
分类总数:9 个
标签数量:251 个
链接总数:10 个
建站日期:
运行天数:1658 天
最后更新:
如果您觉得本站的内容对您有帮助,非要感谢一下不可,那么请给小谢捐赠。C语言与C#之间的转换
怎么将unsigned short int类型转为c#的类型?及c语言里异或、取反与c#的区别(举例说明
09-09-26 &
我们可以使用 System.String 类的构造函数来解决这个问题。System.String 类有两个构造函数是通过字符数组来构造的,即 String(char[]) 和 String[char[], int, int)。后者之所以多两个参数,是因为可以指定用字符数组中的哪一部分来构造字符串。而前者则是用字符数组的全部元素来构造字符串。我们以前者为例,在 TestStringChars() 函数中输入如下语句:char[] tcs = {'t', 'e', 's', 't', ' ', 'm', 'e'};string tstr = new String(tcs);this.textBox1.AppendText(&tstr = \&& + tstr + &\&\n&);运行结果输入 tstr = &test me&,测试说明转换成功。实际上,我们在很多时候需要把字符串转换成字符数组只是为了得到该字符串中的某个字符。如果只是为了这个目的,那大可不必兴师动众的去进行转换,我们只需要使用 System.String 的 [] 运算符就可以达到目的。请看下例,再在 TestStringChars() 函数中加入如如下语名:char ch = tstr[3];this.textBox1.AppendText(&\&& + tstr + &\&[3] = & + ch.ToString());正确的输出是 &test me&[3] = t,经测试,输出正确。
请登录后再发表评论!动态链接库(Dynamic
Link Library&或者&Dynamic-link Library,缩写为&DLL),是window系统的基石。动态链接提供了一种方法,使进程可以调用不属于其可执行代码的函数。函数的可执行代码位于一个
DLL 文件中,该 DLL 包含一个或多个已被编译、链接并与使用它们的进程分开存储的函数。从语言方面来说就是可以在一定程度上使不同的语言之间实现相互调用。本文将实现一个将C语言编译成DLL,供C#调用的例子!
使用环境:vs2012专业版(11.0.50727.1 RTMREL)+ win8.1企业版
1、新建DLL工程
新建项目-&win32-&win32项目-&应用程序设置-&Dll
2、新建testDll.h和testDll.cpp文件,源文件后缀名必须为.cpp
testDll.h文件内容
&span style=&font-size:18&&
#ifndef Test_Dll
#define Test_Dll
extern &C& _declspec(dllexport) char* testChar(char* str);//测试字符串当参数带入以及返回
extern &C& _declspec(dllexport) int testInt(int a,int b);//测试整形,其余浮点型,双精度类似
#endif&/span&
testDll.cpp文件内容
&span style=&font-size:18&&
#include &stdafx.h&
#include &testDll.h&
//以上两个头文件不能调换位置,stdafx.h头文件必须放在第一个,否则将会出错
char* testChar(char* str)//测试字符串当参数带入以及返回
int testInt(int a,int b)//测试整形,其余浮点型,双精度类似
return a +
3、生成项目的解决方案,在项目的debug目录下可以找到生成的TestDllWin32.dll文件
4、新建C#控制台应用程序
在Program.cs中引入System.Runtime.InteropServices,使用DllImport函数引入Dll文件,再使用extern关键字引入所要使用的函数
注意:必须将生成的TestDllWin32.dll文件放到程序的bin目录下的debug目录中,否则必须使用绝对路径引用Dll文件
Program.cs文件内容
&span style=&font-size:18&&namespace Test
class Program
[DllImport(&TestDllWin32.dll&, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
extern static IntPtr testChar(byte[] str);
[DllImport(&TestDllWin32.dll&, CharSet = CharSet.Auto, CallingConvention = CallingConvention.Cdecl)]
extern static int testInt(int a, int b);
static void Main(string[] args)
//使用字符串作为参数传入和接收返回的字符串
string str = &hello world&;
IntPtr ch = testChar(Encoding.ASCII.GetBytes(str));
string result = Marshal.PtrToStringAnsi(ch);
Console.WriteLine(&testChar:\n& + result);//输出:testChar:hello world
//int,float,double类型的传递
int a = 3;
int b = 4;
int reint = testInt(a, b);
Console.WriteLine(&testInt:\n& + reint);//输出:testInt:7
Console.ReadKey();
5、测试结果
------------------------更新-------关于从C#传输中文路径到C里面打开文件的问题-----------------------------
问题:如果从C#传递到C编译而成的DLL中的字符串是一个需要打开的文件的路径名,并且路径名包含中文字符串,那么以上的传递方法将会出现问题,文件无法打开,个人粗浅理解:由于编码格式出错,原因如下图:
注:C语言编译而成的DLL中的CparseXmlFileName方法,只输出传入进去的字符串
传入的字符串:C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt
即使使用UTF8的编码(Encoding.UTF8.GetBytes(Filename))也会出错:
解决办法,使用IntPtr类型,代码如下:
class Program
const string miniXmlDll = &miniXmlDll.dll&;
[DllImport(miniXmlDll, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
extern static IntPtr CparseXmlFileName(IntPtr str);
static void Main(string[] args)
string Filename = &C:\\Users\\TwinklingZ\\Desktop\\ProjectOfTeacher\\minixml解析应用\\Label1.prt&;
var ptr = Marshal.StringToHGlobalAnsi(Filename);
* 测试文件
IntPtr re = CparseXmlFileName(ptr);
Marshal.FreeHGlobal(ptr);
string refile = Marshal.PtrToStringAnsi(re);
Console.WriteLine(&FileName:& + refile);
Console.ReadKey();
}测试结果:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:2711次
排名:千里之外
原创:12篇
(2)(1)(1)(1)(6)(1)

我要回帖

更多关于 成贵高铁最新消息 的文章

 

随机推荐