静态构造函数如何工作? [英] How does a static constructor work?

查看:22
本文介绍了静态构造函数如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

命名空间 MyNameSpace{静态类 MyClass{静态 MyClass(){//认证过程..用户需要输入密码}public static void MyMethod(){//依赖于构造函数的成功完成}}课程计划{静态无效主(字符串 [] args){MyClass.MyMethod();}}}

这是我假设的顺序

  1. 静态构造函数的开始
  2. 静态构造函数结束
  3. main 开始
  4. MyMethod 开始
  5. 主要内容结束

现在在任何情况下,如果 4 将在 2 之前开始,我就完蛋了.可能吗?

解决方案

你在这里只问了一个问题,但你应该问了十几个问题,所以我会回答它们全部.

<块引用>

这是我假设的顺序

  1. 类构造函数的开始(也称为cctor)
  2. 编码器结束
  3. 开始主程序
  4. MyMethod 开始

<块引用>

这是正确的吗?

没有.正确的顺序是:

  1. 程序的 cctor 的开始,如果有的话.没有.
  2. 程序的结尾,如果有的话.没有.
  3. 主程序开始
  4. MyClass 的 cctor 开始
  5. MyClass 的控制器结束
  6. MyClass.MyMethod 的开始

<块引用>

如果有静态字段初始值设定项怎么办?

在某些情况下,允许 CLR 更改静态字段初始值设定项的运行顺序.有关详细信息,请参阅 Jon 在该主题上的页面:

静态构造函数和类型初始化器的区别

<块引用>

是否有可能在该类的 cctor 完成之前调用像 MyMethod 这样的静态方法?

是的.如果 cctor 本身调用 MyMethod 那么显然 MyMethod 将在 cctor 完成之前被调用.

<块引用>

cctor 不调用 MyMethod.是否有可能在 MyClass 的 cctor 完成之前调用像 MyMethod 这样的静态方法?

是的.如果 cctor 使用另一种类型,其 cctor 调用 MyMethod,则 MyMethod 将在 MyClass cctor 完成之前被调用.

<块引用>

没有ccctors直接或间接调用MyMethod!现在是否有可能在 MyClass 的 cctor 完成之前调用像 MyMethod 这样的静态方法?

没有

<块引用>

即使涉及多个线程也是如此吗?

是的.在可以在任何线程上调用静态方法之前,cctor 将在一个线程上完成.

<块引用>

cctor 可以被多次调用吗?假设两个线程都导致 cctor 运行.

无论涉及多少线程,cctor 都保证最多被调用一次.如果两个线程同时"调用 MyMethod,则它们会竞争.其中一个输掉比赛并阻塞,直到 MyClass cctor 在获胜线程上完成.

<块引用>

丢失的线程阻塞,直到 cctor 完成?真的吗?

真的.

<块引用>

那么,如果 获胜 线程上的 cctor 调用阻止 失败 线程先前占用的锁的代码怎么办?

然后你就有了一个经典的锁顺序反转条件.你的程序死锁了.永远.

<块引用>

这看起来很危险.如何避免死锁?

如果这样做会很痛,那么停止这样做.永远不要做会阻塞控制器的事情.

<块引用>

依靠 cctor 初始化语义来强制执行复杂的安全要求是一个好主意吗?有一个负责用户交互的 cctor 是个好主意吗?

都不是好主意.我的建议是您应该找到一种不同的方法来确保满足您的方法的影响安全的先决条件.

namespace MyNameSpace
{
    static class MyClass
    {
        static MyClass()
        {
            //Authentication process.. User needs to enter password
        }

        public static void MyMethod()
        {
            //Depends on successful completion of constructor
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass.MyMethod();
        }
    }
}

Here is the sequence which I assumed

  1. Start of static constructor
  2. End of static constructor
  3. Start of main
  4. Start of MyMethod
  5. End of main

Now in any scenario if 4 will start before 2 I am screwed. Is it possible?

解决方案

You only asked one question here but there are a dozen or so questions that you should have asked, so I'll answer them all.

Here is the sequence which I assumed

  1. Start of class constructor (also known as cctor)
  2. End of cctor
  3. start of Main
  4. start of MyMethod

Is this correct?

No. The correct sequence is:

  1. Start of cctor for Program, if there is one. There is not.
  2. End of cctor for Program, if there is one. There is not.
  3. Start of Main
  4. Start of cctor for MyClass
  5. End of cctor for MyClass
  6. Start of MyClass.MyMethod

What if there is a static field initializer?

The CLR is permitted to change the order in which static field initializers run in some cases. See Jon's page on the subject for details:

The differences between static constructors and type initializers

Is it ever possible for a static method like MyMethod to be called before the cctor of that class completes?

Yes. If the cctor itself calls MyMethod then obviously MyMethod will be called before the cctor completes.

The cctor does not call MyMethod. Is it ever possible for a static method like MyMethod to be called before the cctor of MyClass completes?

Yes. If the cctor uses another type whose cctor calls MyMethod then MyMethod will be called before the MyClass cctor completes.

No cctors call MyMethod, directly or indirectly! Now is it ever possible for a static method like MyMethod to be called before the cctor of MyClass completes?

No.

Is that still true even if there are multiple threads involved?

Yes. The cctor will finish on one thread before the static method can be called on any thread.

Can the cctor be called more than once? Suppose two threads both cause the cctor to be run.

The cctor is guaranteed to be called at most once, no matter how many threads are involved. If two threads call MyMethod "at the same time" then they race. One of them loses the race and blocks until the MyClass cctor completes on the winning thread.

The losing thread blocks until the cctor is done? Really?

Really.

So what if the cctor on the winning thread calls code that blocks on a lock previously taken by the losing thread?

Then you have a classic lock order inversion condition. Your program deadlocks. Forever.

That seems dangerous. How can I avoid the deadlock?

If it hurts when you do that then stop doing that. Never do something that can block in a cctor.

Is it a good idea to rely upon cctor initialization semantics to enforce complex security requirements? And is it a good idea to have a cctor that does user interactions?

Neither are good ideas. My advice is that you should find a different way to ensure that the security-impacting preconditions of your methods are met.

这篇关于静态构造函数如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆