I'd like to offer a list of constants within my DLL.
Example usage:
MyDLL.AddHouse( HouseName, MyDll.HOUSETYPES.Big)
MyDLL.AddHouse( HouseName, MyDll.HOUSETYPES.Small)
Tried:
public static readonly string[] HOUSETYPES =
{
"Big", "Small"
};
But that only gets me:
MyDLL.AddHouse( HouseName, MyDll.HOUSETYPES.ToString())
Any ideas? Thanks.
Try using an enumeration. In C# this is the best option.
As the enumerations are strongly typed, instead of having an API that takes a string, your api will take a value of the type of your enumeration.
public enum HouseTypes
{
Big,
Small
}
MyDll.Function(HouseTypes Option)
{
}
You can then call this code via the enum
{
MyDll.Function(HouseTypes.Big)
}
FYI as a coding style all caps in C# is reserved for constants only.
public static class HouseTypes
{
public const string Big = "Big";
public const string Small = "Small";
}
It is a good idea to follow .NET naming standards for naming your classes and variables. E.g. class will be called HouseTypes (Pascal Case) and not HOUSETYPES (Upper case).
Related
I came from C/C++, and used alot things like #define OBJ_STATE_INPROCESS 2, so that when coding actual logic you can have state = OBJ_STATE_INPROCESS;, and what it does become more obvious than state = 2;, which makes the code easier to maintain.
I wonder if there is some trick like this in C#
Though technically a different concept, in C# you can use contants and enums to avoid "magic numbers", e.g.
public static class Constants
{
public const string MyConst = "ThisIsMyConst";
}
public enum MyEnum
{
MyEnumValue1,
MyEnumValue2,
}
// Usage
var value = MyEnum.MyEnumValue2;
You can accomplish that using constant properties, for example:
static class Constants
{
public const int OBJ_STATE_INPROCESS = 2
}
class Program
{
static void Main()
{
Console.WriteLine(Constants.OBJ_STATE_INPROCESS ); //prints 2
}
}
We have a large class that contains a bunch of css selectors stored as static strings. Example:
public class Constants
}
public static string Selector1 = "#someID";
public static string Selector2 = ".some.classes a";
// and so on...
}
We now need to test a different version of our web app which requires a few different selectors. So we need to find a clean scalable way to override these selectors based on some configuration.
My solution to the problem is this: I'm trying to create a BaseConstants class which will have the current set of selectors. Then I create another class called UpdatedConstants which will subclass the BaseConstants class. This class will then contian all the selectors and just override the ones that need changing with the new keyword. Example:
public class UpdatedConstants : BaseConstants
{
// Overrides the base class's Selector1 string
public new static string Selector1 = "#someOtherID";
}
This works well for overriding the strings however I'm stumped as to how the project will decide which static class to use when it is compiled. All our existing code uses the Constants class like this:
var element = driver.GetElement(Constants.SomeSelector);
Is there a way to dynamically decide which class is the final Constants class? Perhaps by some meta-programming magic?
Let me know if anyone has questions or needs a better explanation of the problem. Thanks
Make your constants classes non-static and use a singleton. This also lets you use virtual properties, since you want to use a base Constants class.
public static class Constants
{
static Constants()
{
#if FOO
Current = new ConstantsFoo();
#elif BAR
Current = new ConstantsBar();
#endif
}
public static ConstantsBase Current { get; private set; }
}
//...snip
var element = driver.GetElement(Constants.Current.SomeSelector);
If you don't want to change all occurences Constants.SomeSelector, the only way to have different behavoirs is using pre-processor directives in the Constants class:
public class Constants
}
#if OLD
public static string Selector1 = "#someID";
#elif NEW
public static string Selector1 = "#someNewID";
#endif
public static string Selector2 = ".some.classes a";
// and so on...
}
Else you can use the approach from Ed Plunketts answer.
Okay, probably not what you're looking for, but... You might want to consider not doing it like this.
Put it this way - if you travel down the road, what will your code look like in 5 years? You'll have a base class that contains your original settings, a subclass for how they were modified the first time (when you asked this question), a subclass inheriting from that subclass on how they were modified the next time, and so on. I could easily imagine 10 subclasses in a giant chain - and if you wanted to trace the current value for any setting, you'd have to travel up that chain until you found where it was most recently set/overriden. It sounds like a maintenance nightmare, to be honest.
If I were in your shoes, this is what the new code would look like:
public static class Constants
{
public static string Selector1 { get { return ReadFromSettings("Selector1"); } }
public static string Selector2 { get { return ReadFromSettings("Selector2"); } }
//etc
// then, code for ReadFromSettings()
}
... and then migrate those settings into an actual settings file. Nobody needs to change any code on the calling end (they still reference Constants.Selector1) - except, instead of having this all hard-coded in a series of derived classes, you just have a file with your values.
In Java, it's possible to have methods inside an enum.
Is there such possibility in C# or is it just a string collection and that's it?
I tried to override ToString() but it does not compile. Does someone have a simple code sample?
You can write extension methods for enum types:
enum Stuff
{
Thing1,
Thing2
}
static class StuffMethods
{
public static String GetString(this Stuff s1)
{
switch (s1)
{
case Stuff.Thing1:
return "Yeah!";
case Stuff.Thing2:
return "Okay!";
default:
return "What?!";
}
}
}
class Program
{
static void Main(string[] args)
{
Stuff thing = Stuff.Thing1;
String str = thing.GetString();
}
}
You can write an extension method for your enum:
How to: Create a New Method for an Enumeration (C# Programming Guide)
Another option is to use the Enumeration Class created by Jimmy Bogard.
Basically, you must create a class that inherits from his Enumeration. Example:
public class EmployeeType : Enumeration
{
public static readonly EmployeeType Manager
= new EmployeeType(0, "Manager");
public static readonly EmployeeType Servant
= new EmployeeType(1, "Servant");
public static readonly EmployeeType Assistant
= new EmployeeType(2, "Assistant to the Regional Manager");
private EmployeeType() { }
private EmployeeType(int value, string displayName) : base(value, displayName) { }
// Your method...
public override string ToString()
{
return $"{value} - {displayName}!";
}
}
Then you can use it like an enum, with the possibility to put methods inside it (among another things):
EmployeeType.Manager.ToString();
//0 - Manager
EmployeeType.Servant.ToString();
//1 - Servant
EmployeeType.Assistant.ToString();
//2 - Assistant to the Regional Manager
You can download it with NuGet.
Although this implementation is not native in the language, the syntax (construction and usage) is pretty close to languages that implement enums natively better than C# (Kotlin for example).
Nope. You can create a class, then add a bunch of properties to the class to somewhat emulate an enum, but thats not really the same thing.
class MyClass
{
public string MyString1 { get{ return "one";} }
public string MyString2 { get{ return "two";} }
public string MyString3 { get{ return "three";} }
public void MyMethod()
{
// do something.
}
}
A better pattern would be to put your methods in a class separate from your emum.
Since I came across, and needed the exact opposite of enum to string, here is a Generic solution:
static class EnumExtensions {
public static T GetEnum<T>(this string itemName) {
return (T) Enum.Parse(typeof(T), itemName, true);
}
}
This also ignores case and is very handy for parsing REST-Response to your enum to obtain more type safety.
Hopefully it helps someone
C# Does not allow use of methods in enumerators as it is not a class based principle, but rather an 2 dimensional array with a string and value.
Use of classes is highly discouraged by Microsoft in this case, use (data)struct(ures) instead; The STRUCT is intended as a light class for data and its handlers and can handle functions just fine. C# and its compiler don't have the tracking and efficiency capabilities as one knows from JAVA, where the more times a certain class / method is used the faster it runs and its use becomes 'anticipated'. C# simply doesn't have that, so to differentiate, use STRUCT instead of CLASS.
I'm working on this project and I have a large number of "services" to execute. I need to have this service codes so I can verifiy and make decisions according to selected services by it's code.
I'm tring to define this enum and get its values from the web.config so I can change them easily.
public enum ServiceCodes
{
Transfer= Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"]),
ChangePlate= Convert.ToInt32(ConfigurationManager.AppSettings["servChangePlate"])
}
But I get this error: The expression must be constant. (because of the Conversion)
What can I do? (Or you can suggest me totally different approaches.)
Just go ahead and define a static class like this:
public static class ServiceCodes
{
readonly static int Transfer = Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"])
//...
}
The documentation states that enum values are constant. An alternative approach is to declare a class with static readonly members.
If you still need the type safety provided by an enum, you could use a slightly complex approach:
public class ServiceCodes {
public static readonly ServiceCodes Transfer = new ServiceCodes(Convert.ToInt32(ConfigurationManager.AppSettings["servTransfer"]));
public static readonly ServiceCodes ChangePlate = new ServiceCodes(Convert.ToInt32(ConfigurationManager.AppSettings["servChangePlate"]));
internal int Code {get; private set;}
private ServiceCodes(int code) {
Code = code;
}
}
Then, a method like:
public void SomeAction(ServiceCodes serviceCode) {
//....
}
could be called like this:
SomeAction(ServiceCodes.Transfer);
But, given the complexity (compared with the gain), I would go with the first approach.
Using VS2010 and .net V4.0 I would like to achieve the following:
I already have 2 resource files in my project for 2 languages - English and Czech.
I must say Resource Management in .net is excellent, I am suprised even to get code completion when implementing a String for example:
string desc = Strings.ResourceManagerDesc
This gets the string associated with the current culture of the thread.
Now I am trying to create an Enum that can have the String portion of the Enum interpreted from the Strings resources. In the following way (This code DOES NOT WORK):
public enum DownloadStatus
{
1 = Strings.DownloadState_Complete,
2 = Strings.DownloadState_Failed,
3 = Strings.DownloadState_InProgress
}
This is a made up example, but you can see the point here. Since the above code won't work, is there a best practice way to achieve what I want?
This question is old but does not have an accepted answer and I was looking for a good way to do this.
Here's what I did, I built an extension to my Enum so that it returns a value from the Resource Manager :
public enum EventType
{
NewVersion = 1,
Accepted = 2,
Rejected = 3,
BruteForce = 4
}
public static class EventTypeExtension
{
public static string Display(this EventType type)
{
return Strings.ResourceManager.GetString("EventType_" + type);
}
}
I hope this can help someone!
Enums cannot inherit from strings. In code you do not need to be concerned with the language of the code, so your enum can simply contain the relevant states.
Looks like what you need is a utility method to convert the enum value to the relevant string representation - simply make a method for this.
EDIT: when you use an enum to switch on cases, but need further information per enumerated value, I tend to drop the enum and create a host of static references and use those in the check instead. This reference can be a class wrapping an enum value, which could then expose helpful titles or descriptions.
Enums are compiled up as part of the assembly. You're essentially assigning a method to the value of the enum isn't of a constant value - the CLR is not smart enough to work out the value at compile time, it needs to be a constant.
I'd suggest that you create a different enum for each language (forget resources) and use a helper class to return the correct one depending on the langauge-context needed.
IMO, the Enum value should be reflected to the domain and should not specific to UI (language-context).
You may want to do like this
public enum DownloadStatus
{
Complete = 1,
Failed = 2,
InProgress = 3
}
and using some EnumHelper method to get culture specific description in the UI layer
var downloadStatusString = EnumHelper.GetDescription<DownloadStatus>(DownloadStatus.Complete);
and EnumHelper class will read the culture specific string from the Resource file
public static class EnumHelper
{
public static string GetDescription<T>(T value)
where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("value must be Enum.", "value");
}
var name = value.ToString();
string resourceKey = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", typeof(T).FullName, name);
object resource = HttpContext.GetGlobalResourceObject("EnumDescriptions", resourceKey, Thread.CurrentThread.CurrentUICulture);
string description = resource as string ?? name;
return description;
}
}
Note: the resource file name is EnumDescriptions and the key must be this conversion YourNamespace.EnumType_EnumValueInString. (I'm using HttpContext to get the resource value and you might want to change it if you are not using ASP.Net.)
You can get a resource via a string, and since you can convert an enum to a string, this is quite straightforward.
enum Whatever { Ready, Set, Go }
public static string GetEnumerationString(Enum enumeration)
{
string resourceName =
string.Concat(enumeration.GetType().Name, "_", enumeration);
return ResourceManager.GetString(resourceName);
}
Now in this implementation we prefixing all enum resources with the name of the enum. In a project we did it just prevents collisions with other resources and makes them easy to find. You'd have to then ensure adding resources called Whatever_Ready, Whatever_Set and Whatever_Go.
Similarly, if you were to look at the generated code for the static member Strings as you originally wrote you'd probably see:
public static string DownloadStatus_Complete
{
return ResourceManager.GetString("DownloadStatus_Complete", Resource.Culture);
}