C# 在强制转换变量时,语法的最佳实践是什么?

C# 在强制转换变量时,语法的最佳实践是什么?,c#,C#,哪个(如果有的话)更正确?为什么? string someVariable = (string) someOtherVariable; string someVariable = someOtherVariable.ToString(); string someVariable = someOtherVariable as string; 我已经使用了所有三种,但我没有任何偏好,也不理解为什么其中一种优于另一种。这是100%的个人偏好,但对我来说,我使用以下选项: string someVar

哪个(如果有的话)更正确?为什么?

string someVariable = (string) someOtherVariable;
string someVariable = someOtherVariable.ToString();
string someVariable = someOtherVariable as string;

我已经使用了所有三种,但我没有任何偏好,也不理解为什么其中一种优于另一种。

这是100%的个人偏好,但对我来说,我使用以下选项:

string someVariable = (string) someOtherVariable;
转换为子类型或父类型时(例如NetworkStream->Stream)

转换为新类型时(int->string)


我从不使用后一种(作为字符串)方法,主要是因为来自C/C++背景,我更喜欢()方法,而且它更简洁。

这些都不是强制转换的示例

这是一个演员阵容:

string someVariable = (string) someOtherVariable;
这是方法调用:

string someVariable = someOtherVariable.ToString();
这是一个安全的演员阵容:

string someVariable = someOtherVariable as string;

第一个和第三个示例是实际的强制类型转换。第一个强制转换可能会抛出一个
InvalidCastException
,而第三个示例不会抛出该异常。这就是为什么
as
操作符被称为安全强制转换的原因。

如果您认为在向上强制转换期间转换将失败,那么as关键字非常有用。例如,如果我想对控件列表中的类似类型执行相同的操作。。。假设取消选中所有复选框:

foreach (Control ctrl in Controls)
{
    Checkbox box = ctrl as Checkbox;
    if (box != null)
        box.Checked = false;
}

这样,如果我的列表有其他内容,如文本框或标签,则不会引发异常(如果失败,只需将变量设置为null),而且非常有效。没有例外的开销。

带括号的强制转换和带“as”的强制转换有很大区别

基本上,括号将引发异常,而“as”将返回null,而不是引发异常

更详细的信息

这是你以前的正常铸造,如果你试图将某个东西铸造成无法铸造的东西,它会抛出一个异常(因此有时你需要检查它们是否可铸造)

不是真正的强制转换,它执行的方法可能来自不同的地方(接口),但C#中的所有对象都有,因为它们继承自拥有它的对象。它有一个默认操作,该操作提供了对象类型的名称,但是您可以重载它来打印您希望类在ToString方法上打印的任何内容

string someVariable = someOtherVariable as string;
这是一个新的c#强制转换,它将首先通过使用
变量is string
检查它是否可强制转换,然后执行强制转换,如果它有效,或者如果它无效,则返回null,因此如果您希望出现异常,则可能是一个无声错误,因为您应该检查null

基本上

myType as myOtherType 
同:

var something = null;
if(myType is myOtherType)
{
  something = (myType) myotherType;
}

除了as将在一个步骤中检查和转换,而不是在2中。

这里不应混淆转换和转换的概念。强制转换涉及将对象视为另一种类型。转换涉及将对象转换为另一种类型

如果您打算将其转换为字符串,则应使用第一个或第三个。(选项取决于您希望在错误情况下发生什么。请参阅的答案。)


如果您打算转换为字符串,则应使用第二个。(或者更好,使用三元运算符修改语句。)这是因为
ToString
方法的行为被定义为将对象转换为字符串表示形式。

这三种方法的作用不同——没有一种更“正确”,这取决于您的情况。如果您有一组可能不是字符串的对象,您可能会使用.ToString()(如果希望为null,则使用null检查)

如果您只关心非null字符串,但仍然希望接收非字符串,请使用“as”转换,然后忽略作为null输入的值(它们最初为null,或者是非字符串类型)

如果希望只接收字符串,最好使用(字符串)强制转换。这在代码中最能表达意图

object foo = 5;
string str = (string)foo;    // exception
string str = foo as string;  // null
string str = foo.ToString(); // "5"

object foo = "bar";
string str = (string)foo;    // "bar"
string str = foo as string;  // "bar"
string str = foo.ToString(); // "bar"

object foo = null;
string str = (string)foo;    // null
string str = foo as string;  // null
string str = foo.ToString(); // exception

首先,你应该。这篇文章解释了原因

第二,只有在期望值不属于您强制转换的类型时,才可以使用作为运算符。因此,您必须手动检查

另外,
obj.ToString()
方法调用不是强制转换,它将对象转换为字符串表示形式(如果字符串本身是相同的字符串)。这可以由任何类验证


因此,作为一般规则,我遵循以下原则:

  • 始终使用
    (类型)
    铸造
  • 仅当对象可以是除强制转换对象以外的其他类型时,才使用
    作为
    运算符
  • 如果使用
    作为
    运算符-始终检查结果是否为空
  • 只有在需要显示有关对象的信息时,才使用
    ToString

  • 这是我关于这个主题的文章

    至于哪一个是“最正确的”,最正确的是你打算传达给节目读者的意思

    “ToString()”表示“这可能不是字符串;如果不是,则我希望从对象获取表示它的字符串。”

    “cast”操作符表示“这是一个字符串,如果我错了,我愿意让我的程序崩溃”,或者相反,“这不是一个字符串,我想调用此对象上的用户定义转换为字符串”

    “as”运算符表示“这可能是一个字符串,如果不是,我希望结果为null。”


    你指的是这四件事中的哪一件

    如果您对强制转换变量时语法的最佳实践有疑问,那么我更愿意使用下一个:

    var someVariable = someOtherVariable as string ?? string.Empty;
    
    当然,您可以使用someVariableDefaultValue而不是string.Empty

    如果不强制转换为字符串,而是转换为某个复杂类型,那么我建议使用下一种语法,有时称为安全导航运算符:

    var complexVariable = otherComplexVariable as ComplexType;
    if (complexVariable?.IsCondition)
    {
       //your code if cast passed and IsCondition is true
    }
    else
    {
       //your code if cast not passed or IsCondition is false
    }
    

    如果我不能将其他变量转换为字符串,安全转换将做什么?@Deane:它将返回null。值得一提的是,
    ToString
    方法基本上要求其他变量将自身表示为字符串,而默认实现(从对象继承)只返回
    object foo = 5;
    string str = (string)foo;    // exception
    string str = foo as string;  // null
    string str = foo.ToString(); // "5"
    
    object foo = "bar";
    string str = (string)foo;    // "bar"
    string str = foo as string;  // "bar"
    string str = foo.ToString(); // "bar"
    
    object foo = null;
    string str = (string)foo;    // null
    string str = foo as string;  // null
    string str = foo.ToString(); // exception
    
    var someVariable = someOtherVariable as string ?? string.Empty;
    
    var complexVariable = otherComplexVariable as ComplexType;
    if (complexVariable?.IsCondition)
    {
       //your code if cast passed and IsCondition is true
    }
    else
    {
       //your code if cast not passed or IsCondition is false
    }