简体   繁体   English

了解静态类和静态方法

[英]Understanding Static Class and static method

Let's say I have a method like this: 假设我有一个这样的方法:

public class MyDataAccess
{
    public static StudentDataTable GetStudentRecords(int schoolID)
    {
        var ta = new StudentTableAdapter();
        using (ta.Connection = new SqlConnection(GetCS()))
        {
            var result = ta.GetStudentRecords(schoolID);
            return result;
        }
    }
}

If this method is accessed 1,000 times at a single time, using a console app or any other means, would there be any chance of it returning records for one school's student to another school? 如果使用控制台应用程序或任何其他方式一次访问此方法1,000次,那么是否有可能将一所学校的学生的记录返回另一所学校?

eg 例如

var records1 = GetStudentRecords(1);
.....
var records1000 = GetStudentRecords(1000);

Is there any chance of the records1 variable getting records of schoolID = 1 mixed with records from records1000 , even if they calls come from their own threads? 即使records1变量的调用来自自己的线程,是否有可能使schoolID = 1记录与records1000记录混合在一起?

Also what is going to happen if I change this class to static as well? 另外,如果我也将此类更改为static,将会发生什么?

My understanding at this point 我目前的理解

1) Yes, I understand what a class is 1)是的,我知道什么是课程

2) Yes, I know static classes don't need required instances to be used 2)是的,我知道静态类不需要使用必需的实例

3) I know simple static code should be there, for example converting datatypes. 3)我知道应该有简单的静态代码,例如转换数据类型。

But what I am confused with is: 但是我感到困惑的是:

What happens when there is a single, static class and there are a million objects trying to access the same object in STACK 当只有一个静态类并且有上百万个对象试图访问STACK中的同一对象时会发生什么

especially when it's a dataAccess class, or a class which accesses activeDirectory objects. 特别是当它是dataAccess类或访问activeDirectory对象的类时。

I had a chat in the programmers SE chat room. 我在程序员SE聊天室聊天。 They didn't say it explicitly, but I got the impression to never use static classes for querying eg sql, active directory, etc.. And that static classes should be limited to simple static code only - no querying. 他们没有明确说出来,但是我的印象是永远不要使用静态类进行查询,例如sql,活动目录等。而且,静态类应仅限于简单的静态代码-不进行查询。

Looking at the code you've given us, the code seems thread-safe. 查看您提供给我们的代码,该代码似乎是线程安全的。 There is no (in-memory) data being shared between threads. 线程之间没有共享(内存中的)数据。

My only concern would be at the db layer - make sure you're using the correct isolation level to avoid dirty reads. 我唯一关心的是db层-确保使用正确的隔离级别以避免脏读。

Also what going to happen if I change this class to static as well. 同样,如果我也将此类更改为静态,将会发生什么。

In regards to GetStudentRecords ? 关于GetStudentRecords Nothing. 没有。


Here's a classic example of thread-unsafe code. 这是线程不安全代码的经典示例。

public class MyDataAccess
{

    private static int _retrievalCount = 0;

    public static StudentDataTable GetStudentRecords(int schoolID)
    {
        _retrievalCount ++;

        // retrieve and return records;            
    }
}

The field _retrievalCount is shared across threads. _retrievalCount字段在线程之间共享。 And the operation ++ is not atomic. 并且++操作不是原子的。 That is, it involves three steps 也就是说,它涉及三个步骤

  1. retrieving the integered stored in _retrievalCount 检索存储在_retrievalCount中的_retrievalCount
  2. adding 1 to it 加1
  3. and storing the result back in _retrievalCount . 并将结果存储回_retrievalCount

If two threads do this simultaneously, and these 3 steps are interleaved, then this could happen instead (assume _retrievalCount starts at 0 and there are 2 threads running): 如果两个线程同时执行此操作,并且交错了这三个步骤,则可能会发生这种情况(假设_retrievalCount从0开始,并且有2个线程在运行):

  1. Thread A reads _retrievalCount as 0 线程A读取_retrievalCount为0
  2. Thread A adds 1 to 0, result = 1 线程A将1加0,结果= 1
  3. Thread B reads _retrievalCount as 0 线程B读取_retrievalCount为0
  4. Thread B adds 1 to 0, result = 1 线程B将1加0,结果= 1
  5. Thread A stores result=1 in _retrievalCount 线程A将结果= 1存储在_retrievalCount
  6. Thread B stores result=1 in _retrievalCount 线程B将结果= 1存储在_retrievalCount

The expected output was 2, but the actual output was 1. 预期输出为2,但实际输出为1。

In C#, "static" merely means that you can call the method directly from the class definition as opposed to calling it against an instance of the class. 在C#中,“静态”仅意味着您可以直接从类定义中调用该方法,而不是针对该类的实例调用该方法。

Think of the "class" as the blueprint for an object. 将“类”视为对象的蓝图。 When you create an instance of an object, the blueprint tells the computer how to create it. 创建对象的实例时,蓝图会告诉计算机如何创建对象。 There are, however, some aspects of the class that don't require an actual object instance, and those aspects are candidates to be provided via "static" methods. 但是,该类的某些方面不需要实际的对象实例,而这些方面都是通过“静态”方法提供的候选对象。

If you change the declaration of your method to include 'static', it changes the way it must be called. 如果将方法的声明更改为包括“ static”,则它将更改必须调用的方式。

public class Example
{   
    static void StaticMethod() {...};  // object instance *not* required
    void InstanceMethod() {...};       // object instance *is* required
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM