简体   繁体   English

静态变量总体最佳实践

[英]Static variable population best practice

I have a class Meterage which I expect to be instantiated several times, probably in quick succession. 我有一个Meterage类,希望可以快速实例化几次。 Each class will need to know the location of the dropbox folder in the executing machine, and I have code for this. 每个类都需要知道dropbox文件夹在执行机器中的位置,我有相应的代码。

The class currently has a variable: 该类当前具有一个变量:

private string dropboxPath = string.Empty;

to hold the path, but I am considering making this a static to save repeated execution of 来保持路径,但我正在考虑将其设为静态,以节省重复执行

this.LocateDropboxFolder();

in the constructor. 在构造函数中。 But I am a little concerned by the switch: what if two constructors try to set this at the same time? 但是,我对转换有点担心:如果两个构造函数尝试同时设置它会怎样? Would this code in the constructor be safe (LocateDropboxFolder becomes static too in this example): 构造函数中的此代码是否安全(在此示例中,LocateDropboxFolder也变为静态):

public Meterage()
{
     if (dropboxPath == string.Empty)
     {
         LocateDropboxFolder();
     }
}

I think my concerns are perhaps irrelevant as long as I don't have construction occurring in multiple threads? 我认为我的担忧可能无关紧要,只要我没有在多个线程中进行构造?

If the field is made static then static field initializers or static constructors are the easy way to initialize them. 如果将字段设为静态,则静态字段初始化程序或静态构造函数是初始化它们的简便方法。 This will be executed at most once in a thread safe manner. 这将以线程安全的方式最多执行一次。

private static string dropboxPath;

static Meterage()
{
    LocateDropboxFolder();
}

If you don't want to re-assign the field I suggest you to use readonly modifier, then the code should look like: 如果您不想重新分配该字段,建议您使用readonly修饰符,则代码应如下所示:

private static readonly string dropboxPath;

static Meterage()
{
     dropboxPath = LocateDropboxFolder();
}

LocateDropboxFolder needs to return a string in this case. 在这种情况下, LocateDropboxFolder需要返回一个字符串。

Variables declared outside the constructor are evaluated before the constructor. 在构造函数外部声明的变量在构造函数之前先求值。 Then the constructor will evaluate it. 然后,构造函数将对其进行评估。

Do remember that you will end up have only one dropBoxPath . 请记住,最终将只有一个dropBoxPath If this is intended, it is okay to do so. 如果有此目的,则可以这样做。 Optionally, make LocateDropboxFolder a static method and call it from the static constructor. (可选)将LocateDropboxFolder静态方法,然后从static构造函数中调用它。

If you want to prevent other constructors to overwrite the default, try this: 如果要防止其他构造函数覆盖默认构造函数,请尝试以下操作:

 if (string.IsNullOrEmpty(dropboxPath))
 {
     LocateDropboxFolder();
 }

Or, in a static constructor (at most called once): 或者,在static构造函数中(最多调用一次):

static Meterage()
{
     LocateDropboxFolder();
}

private static LocateDropboxFolder()
{
    ...
}

Your example will be safe provided your code is executing synchronously. 如果您的代码正在同步执行,那么您的示例将是安全的。 If multiple instances are created, their constructors will be called in the order they are created. 如果创建了多个实例,则将按其创建顺序调用其构造函数。

On the first run through, LocateDropboxFolder() will execute. 在第一次运行时,将执行LocateDropboxFolder() When this completes, dropboxPath will be set. 完成后,将设置dropboxPath

On the second constructor execution, LocateDropboxFolder() will not execute because dropboxPath will no longer equal string.Empty (provided 'LocateDropboxFolder()' does not return string.Empty . 在第二次构造函数执行时, LocateDropboxFolder()将不会执行,因为dropboxPath将不再等于string.Empty (提供的“ LocateDropboxFolder()”不会返回string.Empty

However, if LocateDropboxFolder() is asynchronous or the objects are instantiated on different threads, then it is possible to create a second Meterage instance before dropBoxPath has been set by the LocateDropboxFolder() function. 然而,如果LocateDropboxFolder()是异步或对象被在不同的线程实例化,则有可能建立一个第二Meterage之前实例dropBoxPath已由设定LocateDropboxFolder()函数。 As such, multiple calls to the function will likely be made. 这样,将可能多次调用该函数。

If you wish to guard against multithreading errors like this, you could consider using lock statements . 如果您希望防止此类多线程错误,可以考虑使用lock语句

You might potentially end up running the LocateDropboxFolder multiple times if the object tries to be constructed multiple times in close succession from multiple threads. 如果对象尝试从多个线程中紧接连续构造多次,则可能最终可能会多次运行LocateDropboxFolder As long as the method returns the same result every time though this shouldn't be a problem since it will still be using the same value. 只要该方法每次都返回相同的结果,尽管这不成问题,因为它仍将使用相同的值。

Additionally if you are setting the value of dropboxPath in the constructor then there is no point setting a default value for it. 另外,如果要在构造函数中设置dropboxPath的值,则没有必要为其设置默认值。 I'd just declare it (and not assign it) and then check for null in your constructor. 我只声明它(而不分配它),然后在构造函数中检查null。

I hava a feeling that your Meterage class is breaking a Single Responsibility Principle. 我感觉到您的计量表课程违反了单一责任原则。 What has the meterage to do with a file access? 与文件访问有何关系? I would say you have 2 concerns here: your Meterage and, let's say, FolderLocator. 我要说的是,这里有2个问题:您的Meterage,例如FolderLocator。 the second one should have some property or method like Dropbox which could use lazy evaluation pattern. 第二个应该具有一些属性或方法,例如Dropbox,可以使用惰性评估模式。 It should be instantiated once and this single instance can be injected to each Metarage instance. 应该实例化一次,并且可以将此单个实例注入到每个Metarage实例中。

Maybe not FolderLocator but FileSystem with some more methods than just a single property? 也许不是FolderLocator,而是文件系统具有比单个属性更多的方法? Nos sure what you're actually doing. 不知道你在做什么。 Anyway - make an interface for this. 无论如何-为此建立一个接口。 That would allow unit testing without using the actual Dropbox folder. 这样就可以进行单元测试,而无需使用实际的Dropbox文件夹。

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

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