Would const values be stored per instance?

2019-07-30 00:10发布

问题:

For a type like this:

public class BlurEffect
{
    public const string Name = "Blur";

    public int Amount {get;set;}
}

I have a few members like .Name, that will be the same across all members, should I make it static instead?

I just don't want it to be stored per instance, or use more resources than necessary, and they should also be read-only.

Lastly I want instance access for it so I can say:

blurEffect.Name

Should I make a Name property that returns a private static variable? Is this the best way?

回答1:

Constants, in C#, are actually resolved at compile time. They will be replaced with the value everywhere it's used by the compiler, so the "variable" (Name) won't actually exist in the resulting compiled IL.

String constants, in addition, get interned, so there is only one copy of "Blur" that will be loaded in your executable, no matter how many times its used.

Personally, I would use a private const and a public variable:

public class BlurEffect
{
    private const string name = "Blur";
    public string Name { get { return name; } }

    public int Amount {get;set;}
}

This gets you your instance-based usage, and still has a single constant you can manipulate.



回答2:

Have a read of this:

http://devlicio.us/blogs/joe_niland/archive/2006/09/27/C_2300_-static-readonly-vs-constant-variables_3A00_-when-to-use-each.aspx



回答3:

I personally have never seen any problem with public const variables. However, one thing to consider is if you later need to change the const into a non-constant (or need to do any form of processing when someone gets the value of the constant) then you will break your binary API.

Which means, if this is in the scope of a class library, then if you make such a change later, then every project that links to your class library must be recompiled. You can't just drop in the DLL to make such an update.



回答4:

Constants in .NET are kinda weird. When you define a constant, the compiler enforces object-oriented conventions in your source code, but when the compiler creates the assemblies, any assembly that references this constant, including the assembly in which you declare it, gets the call to the constant reference replaced with a reference to the same value stored in the local assembly's manifest (which stores most "literals"). So, constants are effectively stored per-assembly, and are "static" to every use of that constant within the assembly. The problem is, if you change the constant, you must recompile any assembly that references the constant in order to refresh the manifests on the other assemblies.

Personally, in your case, I would define that value as static, and expose it through a property. This will prevent the value simply being embedded, and will instead place it in a static copy of the object that will be referenced from one place by any assembly in the current AppDomain that needs it (which basically means it's the same everywhere in the application, except for some special cases involving app pools or subdomains).

More info: How Constant Are Your Constants?