I have a Common project inside which I've added my public constants for QueryStringNames.
I know generally constants should be as internal or private but I'd need public constants here as I'd like to allow a global access to the query string names, session keys, etc.
There are 3 solutions that I know of but all of them have an important issue. The caller assembly would contain the copy of my constant which means if I have to change a constant value, I'll have to compile both my Common assembly and the caller assembly!
1) public const string ConstName = "a value";
2) public readonly string ConstName = "a value";
3) To be stored in a public resource file.
What would be the best approach to define public constants in C# apart from storing them in the web.config file (which doesn't have intellisense)?
It depends. If it is truly a constant that won't change, even in future versions of your code, then const is fine. Else go with a static readonly field.
A const will get embedded into the calling assembly, whereas with static readonly the calling assembly only contains a reference to the field. This means const requires recompilation of all dependent code whenever you change the value, whereas public readonly uses the new value even without recompiling the calling assembly.
If you want to store the "constant" in a config file, but like Intellisense, you can use a property with no public setter. And then fill it from the config file at runtime. But I'd argue that configuration values should not be static in the first place. For configuration values I'd use a singleton of some sort, preferably the IoC variation and not the Class.Instance variation. So I'd just define an interface like the following:
interface IMyConfig
{
string Key{get;}
}
And have classes that need this config take it as a constructor parameter:
public MyClass(IMyConfig config)
{
...
}
If you think you'd be changing it and you're worried about having to compile it, then why not use appSettings in the web config file? That's what it's for. If you really need intellisense then you could just put a class in one of the assemblies that reads the config value and exposes it as a property for easier referencing. If it's sensitive data then I wouldn't put it in a config file, I would just compile it anyways since you don't want to compromise your application.
<appSettings>
<add key="myconstant" value="here's the value!" />
</appSettings>
Here's the class to reference that value, which gives you intellisense, ability to change it easily in the future, and without having to recompile anything
public class MyAppConfigSettings
{
public string MyConstant { get; private set; }
public MyAppConfigSettings()
{
MyConstant = ConfigurationManager.AppSettings["myconst"];
}
}
It may not be the answer to your solution but it may give you some other ideas.
If you are activating fxCop (code analysis tool included in Visual studio distribution), you may get sugestion to change constant to become:
public static readonly string ConstName = "a value";
I'm not sure if I understand the problem completely... you're asking for a solution to storing some global variables that won't cause recompiles to assemblies that reference those global variables if you change them? If so then why not try thinking about redesigning your architecture as per the Inversion of Control principle? Think "don't call us, we'll call you" the hollywood principle. If all the assemblies that require some const just call an interface (that they own) that exposes a property with the value they require, and then you have a project of constants that implement those interface (by referencing those projects and then implementing those interfaces) then those projects will never need recompilling when you change the value of the constants.
I'm sure you know them anyway but have a read up on the SOLID principles, "D" being the Dependency Inversion principle (Inversion of Control). I think given your concerns (assuming I've understood you right) they could really help you out.
An example of Inversion of Control could be as simple as:
MyService.dll :
public class MyService
{
// injected dependency
public IMyConstants MyConstants { get; set; }
public MyMethod(){
// get your query...
var query = IMyConstants.Query;
}
}
MyConstants.dll :
public MyConstants : IMyConstants {
// implementation of query property from the myservices.dll interface
public string Query { ... }
}
So the myconstants.dll references the myservice.dll rather than the other way around (meaning myservices won't need recompiling). Then the bootstrapping code (to set it all up and inject dependencies) lives elsewhere.
Sorry if I misunderstood you, hope that helps though!
I prefer the 2nd option in most case since it won't cause problem (by copy value to other assemblies). The speed may have a slower than constants but this kind of nano-second speed is pretty immature.
You could use the Cache object and define them in Global.asax
As said before, it's not the same scenario:
const: is contant and cannot be modified except by recompiling.
readonly: the value is initialized in the declaration or in the constructor and stay readonly after.
When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class
Related
A WinForms application uses the following "configuration class" (partial code):
public class Configuration
{
public static Project currentProject;
}
Many other classes in the application currently use this Project variable, for example:
public class Controller
{
public void processSomething()
{
Configuration.currentProject.doSomething();
}
}
For the purposes of loose coupling, I want to be able to inject a Project variable as a dependency. The problem is, the Configuration.currentProject value might change at runtime. How should this be dealt with? Can passing it by reference solve it?
I'd suggest passing in a Func<IProject> or Func<Project>. This will allow you to nicely handle changes to Configuration.currentProject (since invoking the function will always see the current value of the static) and also allow relatively easy writing of unit tests.
That being said, I'd strongly encourage you to move away from use of static and manual dependency injection. If you used a IoC container (e.g. Autofac) then Func and singleton support (without static) will likely be built in.
I come across this regularly when refactoring code. Say I have a base class and I read some configuration parameters and stuff them into properties like this
public BaseClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
And then I call a method in another class like this
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod(_property1, _property2, _property3);
Is it better to do that? What if I only needed the AppSettings values inside of the OtherClass class? then I could just load them up as private props and initialize them in the constructor and the referencing class/caller wouldn't need to be concerned with the settings.
public OtherClass()
{
_property1 = ConfigurationManager.AppSettings["AppSetting1"];
_property2 = ConfigurationManager.AppSettings["AppSetting2"];
_property3 = ConfigurationManager.AppSettings["AppSetting3"];
}
My implementation would then simply be
OtherClass otherClass = new OtherClass();
var foo = otherClass.SomeMethod();
This one bugs me but I am not really sure why. Which is a better practice and why? And I apologise I am missing something obvious. It happens sometimes lol.
Thanks -Frank
In my view, it depends on what goal of your class.
If class belongs to domain classes, so there is no need to have a dependency to ConfigurationManager class. You can create a constructor and supply necessary data:
public class FooClass()
{
public Property1 {get; private set;}
public FooClass(string property1)
{
Property1 = property1;
}
}
If FooClass belongs to Service Layer, then, in my view, it is eligible to have a dependency to ConfigurationManager class.
I can't really comment on "better" as that's quite subjective, but it's at the very least factual to say that passing the parameters into the method, rather than having the method go and get them itself, is a form of dependency injection. Dependency injection has advantages in that it reduces the number of things the class has to know how to do/reduces the number of other classes any given class needs to do its work. Typically in OO design we look for ways to reduce the dependencies a class has on other classes. You might also see the concept referred to in general as low coupling. Classes that are not highly coupled to other classes are easier to reuse as independent modules within multiple programs
In your example, OtherClass (and/or BaseClass) needs to know what a ConfigurationManager is, which means it needs a reference to its namespace, needs to have system.configuration.dll available on the target etc just so that it can go and get some basic things (strings) that contain info necessary to do its work. If you instead give the strings to the method then it can do its work without knowing what a ConfigurationManager is - you can use it in an app that doesn't even have a ConfigurationManager anywhere, maybe because it gets its config from a database or perhaps it's part of a unit test that gets some contrived data directly from hard coding to ensure a given result is always obtained
When you're down with the concept that the data a class needs to do its work can come from above it starts to make more sense why systems that pass data around like this can work with an inversion-of-control container; essentially software that creates instances of objects for you according to some preconfigured rules about where to get the data that should be passed in. An IoC container can look at an object and decide what arguments to pass to (e.g. its constructor) based on a consistent set of rules, and take another step towards removing dependencies by further reducing use of the word "new". Think of it like writing a config file to describe which of your objects need what instances of other classes to do the work. You craft your IoC container setup so it makes one IniFileConfigSettingsProvider instance and then provides that instance to any object that needs some kind of IConfigSettingsProvider to do its work. Later you switch away form ini files and go to Xml files. You create a class called XmlFileConfigSettingProvider, register it with the IoC and it becomes the new instance that is passed to any class needing an IConfigSettingsProvider. Critically, you made another class, registered it with the IoC and then it gets used throughout your program but you never made an instance of it yourself
If you ever heard the phrase "new is glue" concepts like this are generally what it alludes to - when your OtherClass says var x = new ConfigurationManager... x.Settings["a"].... the use of the word new has suddenly hard wired it to needing a ConfigurationManager; it can't function without knowing what it is. The strive these days is generally to have a class accepting a "passed-in provider of settings that complies with some interface" or "passed-in primitives that are settings" - things that are either implementation specific but obey a generic interface, or ubiquitous in the language and need no special imports respectively. Perhaps either of your mentioned approaches bug you because deep down you feel that neither of them need to depend on ConfigManager; whether they both need settings or not, they can get them passed in, from something higher up the chain that should be making the decisions as to what settings to use
There will be pros and cons of every design and coding choice. As they say, same pattern may not fit everyone. So one has to customize based on need.
Mainly, decision should be based on use cases of your application. Let me provide few scenarios to describe it. Suppose items configured in AppSettings will not change in life-time of the your application then you can have an approach in which dependencies with AppSettings are least. In particular an approach as var foo = otherClass.SomeMethod(_property1, _property2, _property3);. This matches with OOD principles as classes will focus on business logic.
But if you see add/modifying/deleting items (even in rare situations) during life time then above approach would be difficult to maintain. For example without restarting your application/WebServer if AppSettings needs to be reloaded based on certain conditions. One may argue why such settings will be kept in AppSettings, which is very valid too. If your application demands such scenarios then it would be better to use ConfigurationManager.AppSettings without worrying about dependencies. One can opt to extend it have wrapper class (Singleton pattern) to manage and provide access to ConfigurationManager.AppSettings.
I'm creating a lookup class so a constant value will be used throughout all the projects.
The thing is, there are several solutions to create such a thing. I could create a single class with enums, structs or constants in it or create a single class for every 'object'. I'm wondering what would be the best solution.
First I thought doing something like this:
public static class Defines
{
public enum PAGELAYOUT_NAMES
{
STANDARD = "Standard"
}
}
But personally I don't like using strings in enums that much.
Another option would be to use a struct, which is even more ugly if you see the code:
public static class Defines
{
public struct PAGELAYOUT_NAMES
{
public static string STANDAARD = "Standaard";
}
}
This looks a bit better, but could be confusing when having a lot of options:
public static class Defines
{
public const string PAGELAYOUT_NAMES_STANDARD = "Standard";
}
While typing this post, I think this will be the best/clean option:
public static class PageLayout
{
public const string STANDARD = "Standard";
}
Any other suggestions?
Filling up the project with several classes which only define some constants seem to me like a lot of overhead and clutter.
Edit
It wasn't very clear in the original context, but the lookup values aren't limited to only strings. Some very good suggestions below are only possible when you use only strings, but Int's, DateTime and other types need to be supported also. Got some nice ideas from the answers here, I'll try out which one will work best in my current project.
Final implemented solution
Thanks to the suggestions below, I've implemented the lookup classes like this:
internal class Base<T>
{
internal T Value{ get; private set;}
internal Base(T value)
{
Value = value;
}
}
public class PageLayout
{
public static string Standard { get { return new Base<string>("Standard").Value; } }
}
This is based on an answer given below.
Reason is because now I can use this for non-strings & integers also, which isn't really possible with an enum with a description and a resource file, even though that would feel cleaner to me.
Depending on what exactly it is you're doing, you probably want to look at Resources.
You define an xml file (or use the designer to help you), and it gets compiled into an assembly (either embedded, or a "satellite assembly").
Right-click the properties node under your class library in the solution explorer, click "Open" and go to the resources tab. It's pretty simple to get started from there.
Once it's set up, it's easy to get at the values from code e.g:-
String s = Resources.PageLayoutNames.Standard;
There are a few complications, but without knowing more about your app I can't advise more. The one that comes to mind is if you're unit testing ASP.NET applications you need to make sure that the resource gets embedded rather than deployed as a satellite otherwise the unit tests don't work.
They're also used for globalisation, so it's good to be familiar with them.
Edit:
Alternately after reading your question again, I'm inclined to ask "What do you need the string for at all?".
What are you doing that you can't do with just an enum?
enum PageLayouts
{
Standard,
ExtraAwesome
}
If you're trying to map text for display to an enum type, there are a bunch of ways to do that e.g. by using the DescriptionAttribute
enum PageLayouts
{
[Description("Standard")]
Standard,
[Description("Extra Awesome")]
ExtraAwesome
}
You can't give the DescriptionAttribute a resource key out of the box, though. You have to subclass it if you want to support globalisation...
I prefer this way using a factory style static properties. But it depends on the exact scenario. You can use string or enum as the field.
public class PageLayout
{
private readonly string LayoutType;
private PageLayout(string layoutType)
{
LayoutType = layoutType;
}
public static Standard {get {return new PageLayout("Standard");}}
}
Then in calling code use PageLayout.Standard
People advise against public nested classes, so in your earlier examples Defines should be a namespace rather than an outer class.
I always use the
public static class PageLayout
{
public const string STANDARD = "Standard";
}
approach.
I do however create more classes than one: When i use a lot of sessionvariables, i create a (public static)
class SessionNames
And i do make a difference between soultion wide constants and project wide constants.
sometimes the constants for one project (for example 20 placeholders in a PDF you have to create) have nothing to do with the other projects so i make that a project class, but when i have solution wide constants i create a class at the same place as i put my string extensions etc.
I am making a program which makes use of a couple of constants. At first, each time I needed to use a constant, I'd define it as
//C#
private static readonly int MyConstant = xxx;
//Java
private static final int MyConstant = xxx;
in the class where I'd need it. After some time, I started to realise that some constants would be needed in more than one class.
At this time, I had 3 choises:
To define them in the different classes that needed it. This leads to repetition. If by some reason later I need to change one of them, I'd have to check in all classes to replace them everywhere.
To define a static class/singleton with all the constants as public.
If I needed a constant X in ClassA, ClassB and ClassC, I could just define it in ClassA as public, and then have ClassB and ClassC refer to them. This solution doesn't seem that good to me as it introduces even more dependencies as the classes already have between them.
I ended up implementing my code with the second option.
Is that the best alternative? I feel I am probably missing some other better alternative.
What worries me about using the singleton here is that it is nowhere clear to a user of the class that this class is using the singleton. Maybe I could create a ConstantsClass that held all the constants needed and then I'd pass it in the constructor to the classes that'd need it?
Thanks
edit: I'm using this mostly for complex types, not ints and strings. At least in the C# case that makes a difference as it means I can't use the const keyword.
No wording about C#, but in Java there are several ways to solve this problem.
Change the access modifier to default (package-only) or public. The most straightforward solution.
Group them in a package-private or public enum. Most straightforward if those values are related to each other. E.g. Role.ADMIN, Role.USER, Role.GUEST, etc.
Declare them in a package-private or public interface and let the classes implement it. Only do this if those constants belong to some contract the classes have to adhere as well.
Put them in properties files and load as private static final Properties and add a public static String getProperty(String key). Wrap this in some package-private or public Configuration class. More useful if those constants might be sensitive to changes which you could then control externally.
Constants doesn't require to be accessed by an instance, so the whole singleton idea makes no sense.
Use a properties file and put the constants in there.
ConfigurationManager.AppSettings Property in .Net exists for just this reason. You put the settings into config files assuming that these are elements that you want to be set in one place,e.g. for a website using ASP.Net the web.config is one location where settings can be placed so that development, test and production environments can each have different settings in how they run.
As far as int is concerned I usually use an enum in C#
public enum MyMagicNumbers
{
TheFirst = 1,
TheSecond = 2,
TheLast = 10,
}
For other types - like BalusC already mentioned - a sealed class is all you need
public sealed class MyMagicStuff
{
private MyMagicStuff() {}
public const string TheFirst = "One";
public const string TheSceond = "Two";
public const string TheLast = "Ten";
}
I'd define it in one place, in one of the classes that needed it. I'd make it static and final and public so it was true constant, accessible by any other client that needed it.
One approach to this would be to use Spring, available in both Java and .NET.
www.springsource.org
www.springframework.net - .net
Otherwise I'd use a config file.
In Visual Studio 2008 Team System, I just ran Code Analysis (from the Analyze menu) on one of my C# projects. One of the warnings produced was the following:
Microsoft.Design : Because field 'Connection._domain' is visible outside of its declaring type, change its accessibility to private and add a property, with the same accessibility as the field has currently, to provide access to it.
It's referring to the following field:
public abstract class Connection
{
protected string _domain;
}
I don't understand the reasoning behind the suggestion. This is what I think it wants me to do:
public abstract class Connection
{
private string _domain;
protected string Domain { get { return _domain; } set { _domain = value; } }
}
Two questions:
Did I understand correctly what the suggestion wants me to do, code-wise?
Why does it want me to do this?
Yes, I think you understood correctly - although in later versions of C#, there's a more concise way to write it:
public string Domain { get; set; }
Why? It's all about encapsulation. If you do as it suggests, you can later change the definition of the Domain property without affecting any calling code that uses that property. Since your class is public, and might conceivably be called by code that you didn't write, that's potentially quite important.
This is because if you ever wanted to change the field to a property in the future you would break any other assemblies that depend on it.
It is good practice to keep all fields private and wrap them in properties so that you have the option of adding validation or other logic in the future without recompiling all consumers (or in this case inheritors) of your class.
Yep. That's the suggestion. You shouldn't have any accessibility higher than private exposed as direct instance fields.
It's one of the main principles of OOD - encapsulation also referred to as 'data-hiding'.
Yes, you did correct the problem code wise.
It is about encapsulation. _domain is data about your object. Rather then exposing it directly so that any client has unfiltered access, you should provide an interface for them to access it. Practically this might be adding validation to the setter so that it can't be set to any value. It might seem silly if you are the only one writing code because you know how your API works. But try to think about things on a large enterprise level, it is better to have an API so that your object can be seen as a box that accomiplishes a task. You might say you will never have the need to add something like validation to that object, but things are done that way to hold for the possibility of it, and also to be consistent.
Your translation is correct. The same argument for can be made for using 'protected' properties as can be made for using 'public' properties instead of exposing member variables directly.
If this just leads to a proliferation of simple getters and setters then I think the damage to code readablity outweighs the benefit of being able to change the code in the future. With the development of compiler-generated properties in C# this isn't quite so bad, just use:
protected string Domain { get; set; }
In answer to your question... yes.
However, I would just use the auto-property syntax:
public abstract class Connection
{
protected string Domain { get; set; }
}
Basically, properties provide more than returning or setting a member. They allow you to add logic that could verify a proper input format, range validation, etc.
The selected answer from the link puts it best, "Properties provide encapsulation. You can encapulate any needed validation/formating/conversion in the code for the property. This would be difficult to do for fields."
http://social.msdn.microsoft.com/Forums/en-IE/netfxbcl/thread/985f4887-92ae-4ec2-b7ae-ec8cc6eb3a42
In addition to the other answers mentioned here, public/protected members that begin with an underscore are not CLS-compliant, in that there is no requirement for .NET languages to support members with leading underscores, so someone inheriting from your class in a different .NET language may not be able to access that particular protected member.
I know, it probably doesn't apply to you, but it might be part of the reason for the code analysis warning.