I'd like to know if there's a way to include a constructor and methods in an enum in C#. I had something like this in mind:
public enum ErrorCode
{
COMMONS_DB_APP_LEVEL("Application problem: {0}", "Cause of the problem"),
COMMONS_DB_LOW_LEVEL("Low level problem: {0}", "Cause of the problem"),
COMMONS_DB_CONFIGURATION_PROBLEM("Configuration problem: {0}", "Cause of the problem");
private String message;
private String[] argumentDescriptions;
private ErrorCode(String message, String[] argumentDescriptions)
{
this.message = message;
this.argumentDescriptions = argumentDescriptions;
}
public String[] GetArgumentDescriptions()
{
return argumentDescriptions;
}
public String GetKey()
{
return argumentDescriptions();
}
public String GetMessage()
{
return message;
}
}
Obviously, I cannot write an enum like this. How can I accomplish this?
That's not what enums are for. Use a class instead. Here's a quick example:
public class ErrorCode
{
public static readonly ErrorCode COMMONS_DB_APP_LEVEL = new ErrorCode("Application problem: {0}", "Cause of the problem");
public static readonly ErrorCode COMMONS_DB_LOW_LEVEL = new ErrorCode("Low level problem: {0}", "Cause of the problem");
public static readonly ErrorCode COMMONS_DB_CONFIGURATION_PROBLEM = new ErrorCode("Configuration problem: {0}", "Cause of the problem");
private String message;
private String[] argumentDescriptions;
private ErrorCode(String message, params String[] argumentDescriptions)
{
this.message = message;
this.argumentDescriptions = argumentDescriptions;
}
public String[] GetArgumentDescriptions()
{
return argumentDescriptions;
}
public String GetKey()
{
// Need to implement this yourself
}
public String GetMessage()
{
return message;
}
}
Console.WriteLine(ErrorCode.COMMONS_DB_APP_LEVEL.GetMessage(), "Foo");
// Application problem: Foo
A few more suggestions:
Names like COMMONS_DB_APP_LEVEL do not conform to Microsoft's General Naming Conventions.
You should generally use properties rather than methods like GetMessage (Unless your method takes a long time to execute or involves side effects).
You should be careful about returning the array from GetArgumentDescriptions as it allows other code to directly set any elements of the array (even though they can't directly assign a new array). Consider using something like Array.AsReadOnly.
You need to simply use the class and create the enum inside the class and also use the description if you want for every enum value.
public class ErrorCode
{
public enum ErrorCode
{
[Description("Application level problem")]
COMMONS_DB_APP_LEVEL,
[Description("Database level problem")]
COMMONS_DB_LOW_LEVEL,
[Description("Configuration level problem")]
COMMONS_DB_CONFIGURATION_PROBLEM
}
private String message;
private String[] argumentDescriptions;
private ErrorCode(String message, String[] argumentDescriptions)
{
this.message = message;
this.argumentDescriptions = argumentDescriptions;
}
public String[] GetArgumentDescriptions()
{
return argumentDescriptions;
}
public String GetKey()
{
return argumentDescriptions();
}
public String GetMessage()
{
return message;
}
}
because you must use classes instead of enums for writing code something like that. if you are more information for enums you can visit this link.
Related
public class Program
{
public static void Main(string[] args)
{
var c = check.myValue("Example 1"); //This is the pattern I've to use, don't want to create an object (Is it possible to use it with static class)
Console.WriteLine(c.result1);
Console.WriteLine(c.result2);
}
}
public static class check
{
public static void myValue(string qr)
{
public string result1 = "My Name" + qr;
public string result1 = "You're" + qr;
}
}
See here Online Example (Code is not working)
Every thing on main function I've to use exactly the same pattern because I'll use it in a lot of different classes and I don't want to create object each and every time by using non-static class.
Please correct me if I'm wrong
There's a lot wrong with the syntax of that code, which #Sergey addresses in his answer.
You appear to want to return an instance of a class from a static method, and that class should contain two properties.
You can do that by creating the actual, nonstatic class containing the properties:
public class Check
{
public string Result1 { get; set; }
public string Result2 { get; set; }
}
Then return a new instance from the static method therein:
public static Check MyValue(string qr)
{
var result = new Check();
result.Result1 = "My Name" + qr;
result.Result2 = "You're" + qr;
return result;
}
However, you're saying in the comments in your code that you don't want to use an object.
In that case it appears you want to use static properties. That's generally not recommendable, but it would look like this:
public static class Check
{
public static string Result1 { get; set; }
public static string Result2 { get; set; }
public static void MyValue(string qr)
{
Result1 = "My Name" + qr;
Result2 = "You're" + qr;
}
}
Then you can read Check.Result1 after calling the method MyValue().
Your code is totally wrong
myValue method returns void. You cannot assign void return value to variable.
You cannot have public modifiers for local variables.
You cannot have local variables with same name in same scope
If you want to return two values from method, then you should return object with two fields - custom class or tuple. You can also use out parameters, but I don't think it's your case
public static class Check
{
public static Tuple<string, string> MyValue(string qr)
{
return Tuple.Create($"My Name {qr}", $"You're {qr}");
}
}
With C# 7 it's a little bit better. You can write this method in one line and provide names for tuple properties
(string MyName, string YourName) MyValue(string qr) => ($"My Name {qr}", $"You're {qr}");
Usage
var result = Check.MyValue("Example 1");
Console.WriteLine(result.Item1); // result.MyName
Console.WriteLine(result.Item2); // result.YourName
You can practice with creating custom class with nicely named properties instead of using tuples.
I'm about to design a class that more often then not will contain a reference to a Null value. It reminded me of nullable Datetime which has a boolean value to indicate if there is an actual value stored.
DateTime? dt = new DateTime?();
if(dt.HasValue)
{
//DoStuff
}
Is it a good coding practice to design a class as follows?
class Computer
{
public string Name;
public string ID;
//...
public bool IsHiveMind;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
...and to use it...
Computer aComputer = GetComputer(...);
if(aComputer.IsHiveMind)
{
Network.DoHostileTakeOver(aComputer); //!
}
How about this code below?
It seems you can remove IsHiveMind variable since HiveMindInfo variable has the same meaning by checking its null or not.
class Computer
{
public string Name;
public string ID;
public HiveMindInfo RegInfo;
}
class HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
Computer aComputer = GetComputer(...);
if (aComputer != null && aComputer.RegInfo != null)
{
Network.DoHostileTakeOver(aComputer);
}
To answer your question, you could implement the code as proposed.
An alternative would be to consider the following design patterns:
Proxy Design Pattern
Strategy Design Pattern
Sample Code
interface ITakeOverStrategy
{
void Execute();
}
class KevinFlynnHackerStrategy : ITakeOverStrategy
{
public void Execute()
{
// a nod to Tron
}
}
class NeoHackerStrategy: ITakeOverStrategy
{
private readonly HiveMindInfo _hiveMindInfo;
public NeoHackerStrategy(HiveMindInfo info)
{
_hiveMindInfo = info;
}
public void Execute()
{
// Mr. Anderson!
}
}
// This is a surrogate class.
// ... The value returned by String.Empty is often used as a surrogate.
class IdleStrategy : ITakeOverStrategy
{
public void Execute()
{
// do nothing
}
}
class Computer
{
private readonly ITakeOverStrategy _takeoverStrategy ;
public Computer(ITakeOverStrategy strategy)
{
_takeoverStrategy = strategy;
}
public Subjugate()
{
// insert epic code here
_takeoverStrategy.Execute();
}
}
Then somewhere in your code you create an instance of Computer with the appropriate strategy:
var info = new HiveMindInfo();
// update instance parameters
var computer = new Computer(new NeoHackerStrategy(info));
computer.Subjugate();
UPDATES
August 13th, 2015 # 10:13 EST
My comment about structs is not within the scope of the original question, and has been removed:
If your classes are only going to contain fields/properties then I would consider converting them into struct.
Just add ? to your object:
class Computer
{
public string Name;
public string ID;
//...
public HiveMindInfo? RegInfo;
}
struct HiveMindInfo
{
string SecretLocation;
int BaudRate;
int Port;
}
And then check it exactly as you did with datetime:
Computer aComputer = GetComputer(...);
if (aComputer.RegInfo.HasValue)
{
// Do something
}
I am working inside a public BLL with a number of different static methods. Inside a few of these methods, I need to display a certain string to the user depending on an ID# passed into the method. The situation is identical across these few methods. It's currently like this:
public class myBLL
{
public static addByID(int ID)
{
string myString = grabString(ID);
//do some stuff
Console.Writeline("You have added: " + myString);
}
public static removeByID(int ID)
{
string myString = grabString(ID);
//do some other stuff
Console.WriteLine("You have removed: " + myString);
}
public static grabString(int ID)
{
if(ID == 1)
return "string 1";
else
return "string 2";
}
}
I feel like I am violating DRY in myMethod1 and myMethod2 because why bother calling grabString twice? However I cannot come up with a way around this.
What about to use delegate for different parts of methods
public static void myGeneralMethod(int ID, Action<string> method )
{
string myString = grabString(ID);
method(myString);
Console.WriteLine(myString);
}
public static void SomeStuffForAdd(string myString)
{
}
public static void SomeOtherStuffRemove(string myString)
{
}
Or if you want to keep Add/Remove:
public static void removeByID(int ID)
{
myGeneralMethod(ID, SomeStuff);
}
It's a bit hard to evaluate what you really are looking for. But might I suggest some sort of logger? Or maybe a general class that store the value for later use?
public class myBLL
{
public static addByID(int ID)
{
//do some stuff
LogString("You have added: {0}", ID);
}
public static removeByID(int ID)
{
//do some other stuff
LogString("You have removed: {0}", ID);
}
public static LogString(string message, int ID)
{
string myString = "";
if(ID == 1)
myString = "string 1";
else
myString = "string 2";
Console.WriteLine(string.Format(message, myString);
}
}
To be honest, I would remove those static function and create a proper class.
public class MyObject
{
int ID;
public GetString()
{
if(ID == 1)
return "string 1";
else
return "string 2";
}
}
That way, the string could even be cached.
I have a class like this
#region Properties
private static string inputURL;
public static string InputURL
{
get { return inputURL; }
set { inputURL = value; }
}
private static string outputURL;
private static string ffBaseURL = "format=xml&";
public static string FFBaseURL
{
get { return ffBaseURL; }
set { ffBaseURL = value; }
}
private static string excludeParam = "fullurl,log";
public static string ExcludeParam
{
get { return excludeParam; }
set { excludeParam = value; }
}
private static string currentCategoryID = "234";
public static string CurrentCategoryID
{
get { return currentCategoryID; }
set { currentCategoryID = value; }
}
private static string navigationParameters = "query=*&log=navigation&filterCategoryId=" + currentCategoryID;
public static string NavigationParameters
{
get { return navigationParameters; }
set { navigationParameters = value; }
}
#endregion
#region Methods
public static string NavigationCall()
{
List<string> excludeParams = new List<string>(excludeParam.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
foreach (string key in HttpContext.Current.Request.QueryString.Keys)
{
if (!excludeParams.Contains(key))
{
FFBaseURL += key + "=" + HttpContext.Current.Request[key] + "&";
}
}
FFBaseURL += NavigationParameters;
if (Common.IsInternalIP())
{
FFBaseURL += "&log=internal";
}
outputURL = ffBaseURL;
return outputURL;
}
#endregion
As you can see I have a static function called NavigationCall() ,it is mandatory that this function remains static.And when I calls this function from my website the function returns wrong values in each function call because of the static properties i declared.We all know static properties will retain their values after the exection of the programe.
So lets say when i call these function first time I gets a result "tesresult1",second time when i reloads my webpage it gives me a result "testresult1testresult1".I think you got the problem now.
I Have tried to solve this issue by declaring static variable values again ,but it does not looks like a good way to programe things.
I tried to make the properties non static .but it returns error as NavigationCall() is a static function i can't call non static properties inside it.
Now I am searching for a correct way to resolve this issue, I think this problem came to me because of the wrong understanding of OOPS concept.Can any one lend a hand here to solve the case or if the issue is vast point to some resources where i can understand how to find a solution?
Instead of using static properties, you can pass all the parameters to your static method.
public static string NavigationCall(
string inputURL,
string ffBaseURL,
string excludeParam,
string currentCategoryID,
string navigationParameters
)
{
// the body of your method
}
You can also bundled all properties into Custom object and pass it to method. Also you have to make NavigationCall thread safe for any solution. Are static methods thread safe ?
public static string NavigationCall(CustomNavigation objCustomNavigation)
//Custom object.
public class CustomNavigation
{
public string InputURL {get;set;}
public string FBaseURL{get;set;}
public string ExcludeParam{get;set;}
public string CurrentCategoryID {get;set;}
public string NavigationParameters{get;set;}
}
I'd suggest to introduce a parameter object (as #mit suggested) and use the opportunity to encapsulate some of your logic there. This should instantly simplify your method. Maybe you could then make some of these properties private, because they'll only be needed in logic encapsulated in the parameter object.
//Your static method
public static string NavigationCall(CustomNavigation customNavigation)
//Disclaimer: I have no idea, whether this is an appropriate name.
//It really depends on what you want to do with his class
class CustomNavigation
{
public string InputURL { get; private set; }
public string FFBaseURL { get; private set; }
public IEnumerable<string> ExcludeParams { get; private set; }
public string CurrentCategoryID { get; private set; }
public string NavigationParameters { get; private set; }
public CustomNavigation(string inputUrl, string excludeParam, string fBaseUrl, string currentCategoryID, string navigationParameters)
{
// various guard clauses here...
NavigationParameters = navigationParameters;
CurrentCategoryID = currentCategoryID;
FFBaseURL = fBaseUrl;
InputURL = inputUrl;
// Parse string here -> Makes your method simpler
ExcludeParams = new List<string>(excludeParam.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries));
}
//Example for encapsulating logic in param object
public void AddKeys(HttpContext currentContext)
{
var keys = currentContext.Request.QueryString.Keys
.Cast<string>()
.Where(key => !ExcludeParams.Contains(key));
foreach (var key in keys)
FFBaseURL += key + "=" + currentContext.Request[key] + "&";
}
}
In my project I have a generic Packet class. I would like to be able to upcast to other classes (like LoginPacket or MovePacket).
The base class contains a command and arguments (greatly simplified):
public class Packet
{
public String Command;
public String[] Arguments;
}
I would like to have be able to convert from Packet to LoginPacket (or any other) based on a check if Packet.Command == "LOGIN". The login packet would not contain any new data members, but only methods for accessing specific arguments. For example:
public class LoginPacket : Packet
{
public String Username
{
get { return Arguments[0]; }
set { Arguments[0] == value; }
}
public String Password
{
get { return Arguments[1]; }
set { Arguments[1] == value; }
}
}
It would be great if I could run a simple code that would cast from Packet to LoginPacket with something like LoginPacket _Login = (LoginPacket)_Packet;, but that throws a System.InvalidCastException.
It seems like this would be an easy task, as no new data is included, but I can't figure out any other way than copying everything from the Packet class to a new LoginPacket class.
A better approach is to make Packet instance encapsulated by LoginPacket.
This will allow you to do:
LoginPacket _Login = new LoginPacket(_packet);
Also consider creating a PacketFactory where all the logic needed to create various Packet's goes in.
public class Packet
{
public String Command;
public String[] Arguments;
}
public abstract class AbstractPacket
{
private Packet _packet;
public AbstractPacket(Packet packet)
{
_packet = packet;
}
public string this[int index]
{
get { return _packet.Arguments[index]; }
set { _packet.Arguments[index] = value; }
}
}
public class LoginPacket : AbstractPacket
{
public LoginPacket(Packet packet): base(packet)
{
}
public string Username
{
get { return base[0]; }
set { base[0] = value; }
}
public string Password
{
get { return base[1]; }
set { base[1] = value; }
}
}
If different type of Packets differ only by available data members then you could do something below:
Use PacketGenerator to generate packets as:
Packet packet = PacketGenerator.GetInstance(packetdata);
Access the properties as:
Console.WriteLine("User Name: {0}", packet["UserName"]);
Code..
public enum PacketType { Undefined, LoginPacket, MovePacket }
public class PacketData
{
public String Command;
public String[] Arguments;
}
public class Packet
{
public readonly PacketType TypeOfPacket;
private Dictionary<string, string> _argumentMap;
public Packet(PacketType _packetType,
Dictionary<string, string> argumentMap)
{
TypeOfPacket = _packetType;
_argumentMap = argumentMap;
}
public string this[string index]
{
get { return _argumentMap[index]; }
set { _argumentMap[index] = value; }
}
}
public static class PacketFactory
{
Packet GetInstance(PacketData packetData)
{
Dictionary<string, string> argumentMap
= new Dictionary<string, string>();
PacketType typeOfPacket = PacketType.Undefined;
// Replace inline strings/int with static/int string definitions
switch (packetData.Command.ToUpper())
{
case "LOGIN":
typeOfPacket = PacketType.LoginPacket;
argumentMap["UserName"] = packetData.Arguments[0];
argumentMap["PassWord"] = packetData.Arguments[1];
break;
case "MOVE":
typeOfPacket = PacketType.MovePacket;
//..
break;
default:
throw new ArgumentException("Not a valid packet type");
}
return new Packet(typeOfPacket, argumentMap);
}
}