首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C#相当于VB.Net的DirectCast

C#相当于VB.Net的DirectCast
EN

Stack Overflow用户
提问于 2010-04-21 22:32:54
回答 10查看 47K关注 0票数 51

C#有没有和VB.Net的DirectCast等价物?

我知道它有()强制转换和'as‘关键字,但它们与CType和TryCast一致。

为了清楚起见,这些关键字执行以下操作;

CType/()强制转换:如果它已经是正确的类型,则强制转换它,否则查找类型转换器并调用它。如果找不到类型转换器,则引发InvalidCastException。

TryCast/"as“关键字:如果类型正确,则强制转换,否则返回null。

DirectCast:如果它是正确的类型,则强制转换它,否则抛出InvalidCastException。

在我解释了上面的内容之后,仍然有人回应说()是等价的,所以我将进一步阐述为什么这不是真的。

DirectCast只允许在继承树上进行缩小或扩大转换。它不像()那样支持跨不同分支的转换,即:

C# -编译并运行:

代码语言:javascript
复制
//This code uses a type converter to go across an inheritance tree
double d = 10;
int i = (int)d;

VB.NET -这不能编译

代码语言:javascript
复制
'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:

代码语言:javascript
复制
'This compiles and runs
Dim d As Double = 10
Dim i As Integer = CType(d, Integer)
EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2010-04-21 23:31:14

很明显,你想要的功能并不在C#中。试一下这个……

代码语言:javascript
复制
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不同,也可以这样命名:

代码语言:javascript
复制
static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}
票数 14
EN

Stack Overflow用户

发布于 2010-04-22 00:06:47

第二次更新

好的,这是一个C#方法,据说是用来做DirectCast在VB.NET中做的事情的。

代码语言:javascript
复制
static T DirectCast<T>(object o) where T : class
{
    T value = o as T;
    if (value == null && o != null)
    {
        throw new InvalidCastException();
    }
    return value;
}

上面的方法有以下问题:

  1. It有一个where T : class约束,而DirectCast没有。
  2. it将其参数装箱为System.Object --同样,DirectCast不是这样的(至少我不知道)。
  3. 它不必要地使用as (这就是为什么它首先有class约束);如果调用(T)o不起作用,将抛出InvalidCastException;为什么要使用as检查值是否匹配,结果却抛出了与一开始使用(T)o路由时抛出的异常相同的异常呢?

该方法确实可以重写,以提供与DirectCast相同的结果,如下所示:

代码语言:javascript
复制
static T DirectCast<T>(object o) {
    return (T)o;
}

有趣的观察:实际上,这个方法所做的就是对一个值进行装箱,然后尝试将其拆箱。换句话说,DirectCast<int>(12.0)实际上与(int)(object)12.0是一样的(两者都会抛出异常)。意识到这一点使得所提出的DirectCast<T>方法完全没有必要。

现在,这里有一个示例,说明了DirectCast和使用()的转换在VB.NET和C#之间是如何“不同”的:

VB:

代码语言:javascript
复制
Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile '

C#:

代码语言:javascript
复制
int i = 12;
long l = i; // DOES compile

好的,一个可以编译,另一个不能。但是看看代码。当你已经知道一个对象的类型时, DirectCast 有什么意义呢?这不是一个现实的比较,因为在VB.NET中永远不会有任何理由像上面的代码那样调用DirectCast。(如果要将已知为System.Int32类型的值转换为VB.NET中的System.Int64类型的值,则应使用CLng,而不是DirectCast。)如果其中有一个类型为System.Object的变量,则使用DirectCast是有意义的,并且下面的代码确实是等效的:

VB:

代码语言:javascript
复制
Dim i As Integer = 12
Dim o As Object = i
Dim l As Long = DirectCast(o, Long) ' compiles, throws an exception '

C#:

代码语言:javascript
复制
int i = 12;
object o = i;
long l = (long)o; // compiles, throws an exception

因此,我在VB.NET中维护了()**-style,在任何实际有意义使用它的场景中(即,当对象的类型在编译时未知时),与C#**中的直接 cast强制转换是相同的。

EDIT:嗯,我真为我贴出了一些不能编译的VB代码感到羞愧。在重新考虑我所说的话之后,我收回了我的第二个答案,但保留了第一个答案。

如果你指的是DirectCast的用法,当你获取未知类型的对象并试图将其强制转换为所需的类型时,那么它与C#的()强制转换是相同的:

VB:

代码语言:javascript
复制
Dim o As Object = SomeObject()
Dim i As Integer = DirectCast(o, Integer)

C#:

代码语言:javascript
复制
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:

代码语言:javascript
复制
Dim i As Integer = 12
Dim l As Long = DirectCast(i, Long) ' does not compile, actually '

C#:

代码语言:javascript
复制
int i = 12;
long l = i;
票数 8
EN

Stack Overflow用户

发布于 2010-04-21 23:59:25

实际上,如果编译器推断出类型化的变量不能转换为另一种类型,它就会捕获DirectCast冲突。

以下是实际的等价物:

代码语言:javascript
复制
double d = 10;
int i = (int)d;
代码语言:javascript
复制
Dim d As Double = 10
Dim i As Integer = d

注意这个结构的危险。当你只是在VB.NET中将double赋值给整数时,double会被意外地缩小为整数。

尽管C#程序员可以确保编译时的安全性,因为它不会意外地缩小.NET中变量的大小,但VB.NET程序员必须始终将DirectCast作为一种安全的编程习惯。

以下是实际的等价物:

代码语言:javascript
复制
// Will not compile, cannot convert double to int

double d = 10;
int i = d;
代码语言:javascript
复制
' Will not compile, cannot convert double to int

Dim d As Double = 10
Dim i As Integer = DirectCast(d, Integer)

关于Dan Tao's comment

在C#中不需要使用DirectCast。运行库还会阻止将long值加载到整数值。这就是OP的论点,C#没有DirectCast,DirectCast可以阻止不同类型的变量赋值,而“因为”C#没有这个DirectCast,它在赋值不同类型时会默默地出错。但正如你所见,事实并非如此。C#的强制转换和DirectCast完全一样,这会导致一个InvalidCastException运行时错误:

代码语言:javascript
复制
long l = 10;
object o = l;
int i = (int)o;

这也会导致与上面相同的运行时错误:

代码语言:javascript
复制
Dim l As Long = 10
Dim o As Object = l
Dim i As Integer = DirectCast(o, Integer)

现在,这就是“乐趣”的用武之地。使用VB.NET,你必须记住许多关键字才能完成某件事。在C#中,如果一个给定的关键字可以在另一个场景中使用(就像在这个变量转换中),他们不会仅仅为了实现它而发明另一个关键字。

在C#中,您只需执行以下操作:

代码语言:javascript
复制
long l = 10;
object o = l;
int i = (int)(long)o;

在VB.NET中,如果你真的想要向下转换变量,并且想要用正交的方式做到这一点,即只记住一个关键字,你必须这样做:

代码语言:javascript
复制
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中,您必须这样做:

代码语言:javascript
复制
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的安全类型转换行为。它们是一样的!

这种向下的预测。

代码语言:javascript
复制
long l = 1;
int i = (int) l;

...is不等同于:

代码语言:javascript
复制
Dim l As Long = 1
Dim i As Integer = DirectCast(l, Integer)

如果您想要执行向下转换,则必须执行以下操作:

代码语言:javascript
复制
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)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2683847

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档