C#有没有和VB.Net的DirectCast等价物?
我知道它有()强制转换和'as‘关键字,但它们与CType和TryCast一致。
为了清楚起见,这些关键字执行以下操作;
CType/()强制转换:如果它已经是正确的类型,则强制转换它,否则查找类型转换器并调用它。如果找不到类型转换器,则引发InvalidCastException。
TryCast/"as“关键字:如果类型正确,则强制转换,否则返回null。
DirectCast:如果它是正确的类型,则强制转换它,否则抛出InvalidCastException。
在我解释了上面的内容之后,仍然有人回应说()是等价的,所以我将进一步阐述为什么这不是真的。
DirectCast只允许在继承树上进行缩小或扩大转换。它不像()那样支持跨不同分支的转换,即:
C# -编译并运行:
//This code uses a type converter to go across an inheritance tree
double d = 10;
int i = (int)d;VB.NET -这不能编译
'Direct cast can only go up or down a branch, never across to a different one.
Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)在VB.NET中,与我的C#代码等效的是CType:
'This compiles and runs
Dim d As Double = 10
Dim i As Integer = CType(d, Integer)发布于 2010-04-21 23:31:14
很明显,你想要的功能并不在C#中。试一下这个……
static T DirectCast<T>(object o, Type type) where T : class
{
if (!(type.IsInstanceOfType(o)))
{
throw new ArgumentException();
}
T value = o as T;
if (value == null && o != null)
{
throw new InvalidCastException();
}
return value;
}或者,即使它与VB不同,也可以这样命名:
static T DirectCast<T>(object o) where T : class
{
T value = o as T;
if (value == null && o != null)
{
throw new InvalidCastException();
}
return value;
}发布于 2010-04-22 00:06:47
第二次更新
好的,这是一个C#方法,据说是用来做DirectCast在VB.NET中做的事情的。
static T DirectCast<T>(object o) where T : class
{
T value = o as T;
if (value == null && o != null)
{
throw new InvalidCastException();
}
return value;
}上面的方法有以下问题:
where T : class约束,而DirectCast没有。System.Object --同样,DirectCast不是这样的(至少我不知道)。as (这就是为什么它首先有class约束);如果调用(T)o不起作用,将抛出InvalidCastException;为什么要使用as检查值是否匹配,结果却抛出了与一开始使用(T)o路由时抛出的异常相同的异常呢?该方法确实可以重写,以提供与DirectCast相同的结果,如下所示:
static T DirectCast<T>(object o) {
return (T)o;
}有趣的观察:实际上,这个方法所做的就是对一个值进行装箱,然后尝试将其拆箱。换句话说,DirectCast<int>(12.0)实际上与(int)(object)12.0是一样的(两者都会抛出异常)。意识到这一点使得所提出的DirectCast<T>方法完全没有必要。
现在,这里有一个示例,说明了DirectCast和使用()的转换在VB.NET和C#之间是如何“不同”的:
VB:
Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile 'C#:
int i = 12;
long l = i; // DOES compile好的,一个可以编译,另一个不能。但是看看代码。当你已经知道一个对象的类型时, DirectCast 有什么意义呢?这不是一个现实的比较,因为在VB.NET中永远不会有任何理由像上面的代码那样调用DirectCast。(如果要将已知为System.Int32类型的值转换为VB.NET中的System.Int64类型的值,则应使用CLng,而不是DirectCast。)如果其中有一个类型为System.Object的变量,则使用DirectCast是有意义的,并且下面的代码确实是等效的:
VB:
Dim i As Integer = 12
Dim o As Object = i
Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception 'C#:
int i = 12;
object o = i;
long l = (long)o; // compiles, throws an exception因此,我在VB.NET中维护了()**-style,在任何实际有意义使用它的场景中(即,当对象的类型在编译时未知时),与C#**中的直接 cast强制转换是相同的。
EDIT:嗯,我真为我贴出了一些不能编译的VB代码感到羞愧。在重新考虑我所说的话之后,我收回了我的第二个答案,但保留了第一个答案。
如果你指的是DirectCast的用法,当你获取未知类型的对象并试图将其强制转换为所需的类型时,那么它与C#的()强制转换是相同的:
VB:
Dim o As Object = SomeObject()
Dim i As Integer = DirectCast(o, Integer)C#:
object o = SomeObject();
int i = (int)o;这是因为,如果将o类型化为System.Object,则C#中的()操作将尝试对其进行拆箱。如果类型不完全匹配,这将失败;例如,如果o是已装箱的System.Double,则(int)o将抛出异常,因为o 必须先作为System.Double取消装箱,然后才能将其转换为System.Int32 (如果您不相信我,可以亲自尝试一下!)。
注意:下面的内容是不准确的,因为DirectCast 不执行加宽转换;无论如何,我将把它留给后人。
另一方面,在处理扩大转换与缩小转换时,使用C#中的()操作比您所指出的简单类型转换(即,您可以执行(int)someDouble)要做更多的工作。在这个场景中,DirectCast等同于C#中的普通旧赋值:
VB:
Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile, actually 'C#:
int i = 12;
long l = i;发布于 2010-04-21 23:59:25
实际上,如果编译器推断出类型化的变量不能转换为另一种类型,它就会捕获DirectCast冲突。
以下是实际的等价物:
double d = 10;
int i = (int)d;Dim d As Double = 10
Dim i As Integer = d注意这个结构的危险。当你只是在VB.NET中将double赋值给整数时,double会被意外地缩小为整数。
尽管C#程序员可以确保编译时的安全性,因为它不会意外地缩小.NET中变量的大小,但VB.NET程序员必须始终将DirectCast作为一种安全的编程习惯。
以下是实际的等价物:
// Will not compile, cannot convert double to int
double d = 10;
int i = d;' Will not compile, cannot convert double to int
Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)在C#中不需要使用DirectCast。运行库还会阻止将long值加载到整数值。这就是OP的论点,C#没有DirectCast,DirectCast可以阻止不同类型的变量赋值,而“因为”C#没有这个DirectCast,它在赋值不同类型时会默默地出错。但正如你所见,事实并非如此。C#的强制转换和DirectCast完全一样,这会导致一个InvalidCastException运行时错误:
long l = 10;
object o = l;
int i = (int)o;这也会导致与上面相同的运行时错误:
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(o, Integer)现在,这就是“乐趣”的用武之地。使用VB.NET,你必须记住许多关键字才能完成某件事。在C#中,如果一个给定的关键字可以在另一个场景中使用(就像在这个变量转换中),他们不会仅仅为了实现它而发明另一个关键字。
在C#中,您只需执行以下操作:
long l = 10;
object o = l;
int i = (int)(long)o;在VB.NET中,如果你真的想要向下转换变量,并且想要用正交的方式做到这一点,即只记住一个关键字,你必须这样做:
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(DirectCast(o, Long), Integer)但是这不会编译,那么我们如何实现将长整型转换为整数呢?您必须记住VB.NET的其他关键字。而在C#中,它是正交的,你可以使用这个结构(typehere)对变量进行拆箱,你也可以使用相同的结构(typehere)进行向下转换/向上转换。在VB.NET中,从object加载值和向下转换值之间存在根本的脱节。因此,在VB.NET中,您必须这样做:
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = CType(o, Integer)嗯..。我认为OP的混乱源于C#对(typehere)的多次使用。首先,它用于向下转换;其次,同样的构造(请查看本文的第一部分,object o = l)也用于从object中拆箱取值,请放心,它具有DirectCast的安全类型转换行为。它们是一样的!
这种向下的预测。
long l = 1;
int i = (int) l;...is不等同于:
Dim l As Long = 1
Dim i As Integer = DirectCast(l, Integer)如果您想要执行向下转换,则必须执行以下操作:
Dim l As Long = 1
Dim i As Integer = CInt(l) ' Can also use CType现在,如果一个VB.NET程序员是故意编程的,并且在编码时不会打瞌睡,那么当他/她充分意识到它不能分配不同的类型时,为什么他/她会使用DirectCast呢?如果VB.NET程序员真正想要的是向下转换,那么他/她从一开始就不应该尝试DirectCast。现在,VB.NET程序员在发现DirectCast不能用于向下转换时,必须将他/她编写的内容退格,并将其替换为CInt (或CType)。
https://stackoverflow.com/questions/2683847
复制相似问题