【问题标题】:Is C# a type safe language? How about my exampleC# 是一种类型安全的语言吗?我的例子怎么样
【发布时间】:2017-08-30 12:16:09
【问题描述】:

我正在用 C# 测试下面的代码,它可以成功运行。我的问题是我可以在下面的示例中将一种类型的数据分配给另一种类型的数据,但是为什么它仍然被称为类型安全语言?谢谢。

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text.RegularExpressions;

    namespace Rextester
    {
        public class Program
        {
            public static void Main(string[] args)
            {
               var intNum = 5;
               var strNum = "5";
               var result = intNum + strNum;         
               Console.WriteLine(result);
            }
        }
    }

可以编译成功,结果为55。

【问题讨论】:

  • stackoverflow.com/a/3398629/5621827 可能会有所帮助
  • 不,我的问题是 1) C# 是一种类型安全的语言吗?是或否。2)如果答案是肯定的,那么为什么我的代码可以成功编译。这是否意味着我的示例与类型安全问题无关。谢谢。
  • 回答:是的。是的。
  • 对于不同类型的操作符重载没有什么“类型不安全”。如果你想定义一个在FooBar 上工作的加号运算符来创建一个Baz,你可以这样做,它仍然是类型安全的。

标签: c# typesafe


【解决方案1】:

类型安全意味着它确保只有类型定义允许的操作才能应用于对象的内存,例如您不能将对象强制转换为某种不兼容的类型。

关于连接字符串和整数的 + 运算符,这在 C# 4 规范的第 7.8.4 节中指定:

对于 x + y 形式的运算,二元运算符重载 分辨率(第 7.3.4 节)用于选择特定运算符 执行。操作数转换为参数类型 选择的运算符,结果的类型是返回类型 运营商的。

下面列出了预定义的加法运算符。对于数字和 枚举类型,预定义的加法运算符计算总和 的两个操作数。 当一个或两个操作数都是字符串类型时, 预定义的加法运算符连接字符串表示 操作数。

【讨论】:

  • 感谢您的回复。但是,您能在下面简单地回答我的问题吗:1)C# 是一种类型安全的语言吗?是或否。2)如果答案是肯定的,那么为什么我的代码可以成功编译。这是否意味着我的示例与类型安全问题无关。谢谢。
【解决方案2】:

是的。您的示例使用 var 在 C# 中的含义与在 JavaScript 中的含义截然不同。在 C# 中,它更像是一种语法糖。你写的代码相当于下面的 -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           int intNum = 5;
           string strNum = "5";
           string result = String.Concat(intNum, strNum);         
           Console.WriteLine(result);
        }
    }
}

所以基本上,编译器会查看 var 声明的右侧来决定正确的类型。这有点告诉编译器获取类型(严格编译时间),因为我懒得理会。​​p>

但它有更大的用途,它可以让你处理anonymous types

最后,为了毫无疑问地证明var 是真正的类型安全,试试下面的代码 sn-p...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
           var intNum = 5;
           var strNum = "5";
           var result = intNum + strNum;
           // Let's re-purpose result to store an int
           result = 6;
           // or this
           result = intNum;
           Console.WriteLine(result);
        }
    }
}

这在与类型无关的语言(又如 JavaScript)中完全有效。

【讨论】:

    【解决方案3】:

    回答您在 cmets 中重复的问题:

    1. C# 是一种类型安全的语言吗?是或否。

    是的。

    1. 如果答案是肯定的,那为什么我的代码可以编译成功。这是否意味着我的示例与类型安全问题无关。

    您的示例与类型安全问题无关。
    首先注意var只是一个语法糖,编译器会根据右边给你的变量分配正确的类型。

    换句话说,你问为什么以下是有效的:

    int intNum = 5;
    string strNum = "5";
    string result = intNum + strNum;
    Console.WriteLine(result);
    

    这是有效的,因为 .NET 支持这种字符串连接,请参阅下面的 Concat method

    string result = string.Concat(intNum, strNum);
    

    该方法通过调用 ToString 方法连接两个参数。

    【讨论】:

      【解决方案4】:

      来自MSDN

      类型安全代码只访问它被授权的内存位置 使用权。 (对于本次讨论,类型安全特指 内存类型安全,不应与类型安全混淆 更广泛的尊重。)例如,类型安全代码不能从 另一个对象的私有字段。它只访问类型 定义明确、允许的方式。

      在即时 (JIT) 编译期间,可选的验证 过程检查元数据和 Microsoft 中间语言 (MSIL) 一种方法的 JIT 编译为本机代码以 验证它们是类型安全的。如果代码跳过此过程 有权绕过验证。有关更多信息 验证,请参阅托管执行过程。

      虽然类型安全的验证不是运行托管的强制要求 代码,类型安全在程序集隔离和 安全执法。当代码类型安全时,通用语言 运行时可以将程序集彼此完全隔离。这 隔离有助于确保组件不会对每个组件产生不利影响 其他,它增加了应用程序的可靠性。类型安全组件 可以在同一进程中安全执行,即使它们在 不同的层次。当代码不是类型安全时,不需要的副作用 可以发生。例如,运行时不能阻止托管代码 调用本机(非托管)代码并执行恶意代码 操作。当代码类型安全时,运行时的安全实施 机制确保它不会访问本机代码,除非它有 允许这样做。所有不是类型安全的代码都必须是 使用传递的枚举成员授予 SecurityPermission 运行 SkipVerification。

      加上一个shorter explanation

      如果您要问“类型安全”的一般含义是什么,它是 让开发者确定的代码特性 一个值或对象将表现出某些属性(即, 某些类型),以便他/她可以以特定方式使用它而不必担心 意外或未定义的行为。

      ...以及该网址上的深入说明性示例。

      【讨论】:

      • 可能会更好地总结那堵文字墙或至少粗体重要部分
      猜你喜欢
      • 2010-09-12
      • 1970-01-01
      • 2016-08-25
      • 1970-01-01
      • 1970-01-01
      • 2012-12-29
      • 1970-01-01
      • 1970-01-01
      • 2016-06-17
      相关资源
      最近更新 更多