C# 为什么要编译?

C# 为什么要编译?,c#,compiler-errors,null,C#,Compiler Errors,Null,下面的代码编译时没有问题。很明显,\u dependency将始终为null,因此不可能以任何方式使用它(除了评估它)-是吗?为什么编译器没有意识到这一点并失败了呢 public class MyClass { private readonly MyDependency _dependency; public MyClass() { _dependency.MyMethod(); } } 要明确的是,我知道上面的代码是糟糕的代码,这是开发人员的错误——但正

下面的代码编译时没有问题。很明显,
\u dependency
将始终为
null
,因此不可能以任何方式使用它(除了评估它)-是吗?为什么编译器没有意识到这一点并失败了呢

public class MyClass
{
   private readonly MyDependency _dependency;

   public MyClass()
   {
      _dependency.MyMethod();
   }
}
要明确的是,我知道上面的代码是糟糕的代码,这是开发人员的错误——但正如任何其他编译时错误一样。我原以为编译器会抛出一个
使用未赋值变量的错误

为什么要编译?我是否不知道这样使用
null
对象就可以了

编辑:


确认一下——我不希望依靠编译器来检查写得不好的代码——我很感激,从语法上来说,这是绝对好的。我的问题有两个方面,是否有一个我不知道的场景可以使代码正常执行。第二个问题是——如果它已经处理了
未赋值变量的使用
错误,为什么不检测到这样的问题?有什么区别吗?

因为编译器不会检查此类问题。它在语法上是正确的,而且非常好。空引用问题通常只在运行时检测到,除非您使用代码分析工具来检测此类问题。

,因为它并不完全不正确。可能是警告,但肯定不是编译器错误

您可以这样做,例如:

public class MyClass
{
    private readonly MyDependency _dependency;

    public MyClass()
    {
        _dependency.MyMethod();
    }

    public bool IsDependencyNull()
    {
        return _dependency == null;
    }
}

public class MyDependency { public void MyMethod() { } } 
然后使用它:

var c = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));
c.IsDependencyNull().Dump();

给出结果“True”

首先,代码编辑器帮助可能会向您发出警告,说明该字段未分配,并且可能工作错误

其次,您不能在编译时测试成员是否被反射访问。您可以指定字段,即使它是只读的。甚至可以在外部初始化只读字段后调用构造函数。考虑下面的例子:

// creating an instance without executing the constructor
MyClass myClass = (MyClass)FormatterServices.GetUninitializedObject(typeof(MyClass));

// setting the read-only field
myClass.GetType().GetField("_dependency", BindingFlags.NonPublic | BindingFlags.Instance)
    .SetValue(myClass, new MyDependency());

// invoking the constructor on the already existing myClass
ConstructorInfo ctor = typeof(MyClass).GetConstructor(
    BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null);
MethodInfo mi = typeof(RuntimeMethodHandle).
    GetMethod("InvokeMethod", BindingFlags.NonPublic | BindingFlags.Static);
object signature = ctor.GetType().GetProperty(
    "Signature", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(ctor);
mi.Invoke(null, new []{myClass, null, signature, false});

MyDependency
是否声明为类或结构?这会导致运行时错误。属性(与局部变量不同)具有指定的默认值。因此没有编译时错误
未赋值变量的使用
假设
MyDependecy
有一个名为
MyMethod
的方法,代码没有问题。它不是编译器的作业检查对象是否初始化。这是在运行时完成的,或者使用第三种工具来提示(比如Resharper)。想象一下
MyMethod
将是一种扩展方法(当然,它们在旧的C#1-days中还没有被引入)。编译此代码时调用
MyDependency.MyMethod(null)
将被期望编译,不是吗?像resharper这样的工具可以发现这种情况并向您发出警告。但这只是警告。这可能是真的,也可能不是。若编译器在编译时抛出运行时异常,则可能会出现错误。可能有很多原因使此代码能够工作。多线程、反射、非托管库或托管库的使用等…感谢您的回答。根据我对Ben的评论,编译器至少有一些检查执行路径的功能-因为我们有
未赋值变量的使用
错误-我没有看到该场景与我描述的场景之间的差异。这不是什么大问题-我只是好奇为什么编译器没有检测到问题。未分配的变量只会检查函数体中的局部变量。从未使用过的变量不是错误,因此不会停止编译。它只是被优化程序删除了,如果在项目设置中启用代码分析,则将获得更详细的坏代码检查practice@JayMee因为没有“本地”问题。问题在于类的整体性,这比通常的编译器错误更难检测到几个数量级。有一套编译器工具来完成这项工作,代码契约,但运行速度非常慢。