We have some stuff that may be exported into various formats. Currently we have these formats represented by an enum like this:
[Flags]
public enum ExportFormat
{
None = 0x0,
Csv = 0x1,
Tsv = 0x2,
Excel = 0x4,
All = Excel | Csv | Tsv
}
Problem is that these must be enumerated and they also need a translation or description in the ui. Currently I solved this by creating two extension methods. They work, but I don't really like them or the solution at all... they feel kind of smelly. Problem is I don't really know how I could do this better. Does anyone have any good alternatives? These are the two methods:
public static IEnumerable<ExportFormat> Formats(this ExportFormat exportFormats)
{
foreach (ExportFormat e in Enum.GetValues(typeof (ExportFormat)))
{
if (e == ExportFormat.None || e == ExportFormat.All)
continue;
if ((exportFormats & e) == e)
yield return e;
}
}
public static string Describe(this ExportFormat e)
{
var r = new List<string>();
if ((e & ExportFormat.Csv) == ExportFormat.Csv)
r.Add("Comma Separated Values");
if ((e & ExportFormat.Tsv) == ExportFormat.Tsv)
r.Add("Tab Separated Values");
if ((e & ExportFormat.Excel) == ExportFormat.Excel)
r.Add("Microsoft Excel 2007");
return r.Join(", ");
}
Maybe this is the way to do this, but I have a feeling there must be better ways to do it. How could I refactor this?
You could use the Formats method inside Describe to avoid doing all the bit operations at multiple places, like this:
private static Dictionary<ExportFormat, string> FormatDescriptions =
new Dictionary<ExportFormat,string>()
{
{ ExportFormat.Csv, "Comma Separated Values" },
{ ExportFormat.Tsv, "Tab Separated Values" },
{ ExportFormat.Excel, "Microsoft Excel 2007" },
};
public static string Describe(this ExportFormat e)
{
var formats = e.Formats();
var descriptions = formats.Select(fmt => FormatDescriptions[fmt]);
return string.Join(", ", descriptions.ToArray());
}
This way, it is easy to incorporate the string descriptions from an external source or localization, as hinted above.
The only other way comes to my mind is the usage of the System.Attribute class.
public class FormatDescription : Attribute
{
public string Description { get; private set; }
public FormatDescription(string description)
{
Description = description;
}
}
And then use Reflection with in your Describe function.
The only benefit of this method would be to have definition and the description at one place.
Dupe: How do I have an enum bound combobox with custom string formatting for enum values?
You could write an TypeConverter that reads specified attributes to look them up in your resources. Thus you would get multi-language support for display names without much hastle.
Look into the TypeConverter's ConvertFrom/ConvertTo methods, and use reflection to read attributes on your enum fields.
Addition:
Scroll down in the linked post for a implementation of a TypeConverter that does part of what is required for full support.
This would support an application where you have several languages at the same time, not only code name -> english name.
Remember that this is only the display name, never the stored value. You should always store the code name, or the integer value, to support users with different locales using the same data.
Related
I have a car class which needs a brand, a type, and the make, for example, SUV, coupe, sedan. I made an enum class for these types. I want to instantiate a new car which needs these arguments. I have to import these data from a text file. The text file contains this: &Peugeot*406%sedan$2002/110. I split the pieces of information into a string array but don't know how to get the make of the car. I hope you understand my problem here is the code :
Car car = new Car(data[0],data[1],int.Parse(data[2]),int.Parse(data[3]),int.Parse(data[4]));
You need to parse the strings into enum equivalents. It is better to use TryParse to avoid exceptions.
Here's a simple example especially written for you :)
enum AutoBrand { Skoda, Toyota, BMW};
enum AutoType { SUV, SEDAN, HATCHBACK};
static void Main(string[] args)
{
string[] strAutoBrands = new string[] { "Skoda", "Toyota", "BMW" };
string[] strAutoTypes = new string [] { "SUB", "SEDAN", "HATCHBACK" };
foreach(var autoBrandVal in strAutoBrands)
{
AutoBrand b = (AutoBrand) Enum.Parse(typeof(AutoBrand), autoBrandVal);
Console.WriteLine($"Auto brand is: {b}");
}
}
Enums are typically used to define a set of constants to use instead of "magic numbers" to make code mode human-readable. They may not be appropriate to use for string-based data like make and model.
However, if you have a string and want to find the equivalent Enum value, use Enum.Parse:
Car car = new Car(
Enum.Parse(typeof(Make),data[0]),
Enum.Parse(typeof(Model),data[1]),
int.Parse(data[2]),
int.Parse(data[3]),
int.Parse(data[4]));
Note that you should add appropriate error hendling, etc. to deal with invalid string values.
I need a c# program ( search algorithm ), ie, When user types a character, the display should update to show all valid choices for the next character and a list of possible matching stations.
Ex: User Input: D A R T, it should display
DARTFORD and DARTMOUTH
Suggested outline is below:
public class Suggestions
{
HashSet<Character> nextLetters { get; set; }
HashSet<String> stations { get; set; }
}
public class StationFinder
{
private static String[] stations = new String[] {"LIVERPOOL LIME STREET", "BIRMINGHAM
NEW STREET", "KINGSTON", " DARTFORD", "DARTMOUTH" };
public Suggestions GetSuggestions( String userInput )
{
// TODO Compute result
Suggestions result = new Suggestions();
return result;
}
}
This is just a suggestion it can be modified as well.
Regards,
Vishnu
I do not know C# personally so I can't help you with the code but what you want to use is called a TRIE. This is a specific type of tree structure for strings. The nice property is you can very see all legal endings given the starting of a string. This is perfect for things like auto suggest etc. and I think is what you want for you thing. just google around for TRIE implementations in C#
What you want is a Ternary search tree look here wikipedia and here c# example
I have a static class where I keep a large number of relative paths that are used in different places in my application. It looks like that:
static class FilePathConstants
{
public const string FirstDirectory = "First";
public const string FirstSecondDirectory = "First/Second";
public const string FirstSecondThirdFileA = "First/Second/Third/FileA";
public const string FirstSecondFourthFileB = "First/Second/Fourth/FileB";
... nearly 100 of similar members
}
All of them are relative to some parent directory, location of which I know only during the program run. I need to keep them all together because it allows me to easily control what files are used by my application and change their locations from time to time.
However even though they are organized in alphabetic order and its easy to find a certain path, I need to be able to change some of them depending on some setting. Lets say, there is a setting 'bool SettingA' and when I turn it on, I have to do modify some of the paths to use a different directory or a different file name.
The problem is that now I can't use constants, I have to rewrite my code to properties or methods so that I can change file paths at runtime. And here where my code becomes much bigger in size and the strict order now looks ugly. Is there a way I can group them, so that it will not confuse anybody who uses this code? I can't break them into a separate classes because it is difficult to remember in what class what constant you may keep. For now I'm grouping them by regions, but I have a bad feeling that keeping more than one hundred of properties in one class is wrong.
Edit:
All directories and files that I declare in FilePathConstants are used in a large number of places in application (each path can be used multiple times, taking into account the fact that there is more then one hundred of paths - this is a large number). I would like to keep the interface of this class the same or with minimum changes to other classes that use them.
maybe you could use rowstructs
Use something like "index" file to store the directory paths and load it in runtime.
const string indexFilePath = #"C:\dirlist.txt";
IEnumerable<string> paths = File.ReadAllLines(indexFilePath);
Update
I would like to suggest using indirection - "mapper" class.
Here is how it should look like.
public enum FileSystemElement
{
FirstDirectory,
FirstSecondDirectory,
FirstSecondThirdFileA,
FirstSecondFourthFileB
}
public class FileSystemMapper
{
private readonly string _rootDirectory;
private readonly Dictionary<FileSystemElement, string> _fileElements;
public FileSystemMapper(string rootDirectory, string fileName)
{
_rootDirectory = rootDirectory;
string[] lines = File.ReadAllLines(fileName);
_fileElements = lines.Select(ParsePair).ToDictionary(pair => pair.Key, pair => pair.Value);
}
public string GetPath(FileSystemElement element)
{
string relativePath;
if (!_fileElements.TryGetValue(element, out relativePath))
{
throw new InvalidOperationException("Element not found");
}
string resultPath = Path.Combine(_rootDirectory, relativePath);
return resultPath;
}
private static KeyValuePair<FileSystemElement, string> ParsePair(string line)
{
const string separator = "|";
// File element alias | Path
if (string.IsNullOrEmpty(line))
throw new ArgumentException("Null or empty line", "line");
string[] components = line.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries);
if (components.Length != 2)
throw new ArgumentException("Line has invalid format", "line");
FileSystemElement element;
bool parseResult = FileSystemElement.TryParse(components[0], out element);
if (!parseResult)
throw new ArgumentException("Invalid element name", "line");
string path = components[1]; // for clarity
return new KeyValuePair<FileSystemElement, string>(element, path);
}
Client example:
FileSystemMapper fileSystemMapper = new FileSystemMapper(#"C:\root", #"C:\dirs.txt");
string firstDirectory = fileSystemMapper.GetPath(FileSystemElement.FirstDirectory);
string secondDirectory = fileSystemMapper.GetPath(FileSystemElement.FirstSecondDirectory);
string secondThirdFile = fileSystemMapper.GetPath(FileSystemElement.FirstSecondThirdFileA);
Index file format: <Element name>|<Path><New Line>
Example:
FirstDirectory|First
FirstSecondDirectory|First\Second
FirstSecondThirdFileA|First\Second\Third\FileA
FirstSecondFourthFileB|First\Second\Fourth\FileB
can you not use your projects Properties.Settings? it's stored in the .config file so can be edited after deployment
or just dont make them const, then you can edit them at runtime bu they revert to the original setting on next run.
or dont make the calss static and create an instance each time you use it, then change whats needed and discard the instance when finished.
Note: I've read this and its not quite what I'm looking for:
I have an app that builds up XML from an input file and creates one of two outputs, depending upon the file chosen. It was a "quick n dirty" app to get round an immediate problem, but I know it's going to find further use and want to pre-empt this by refactoring.
At the moment I have a "builder" class that takes the input (in its ctor) and exposes a property which is the required XElement. However, many of the XElements are identical, except for the content, for both of my XML outputs. (Oh, please ignore the validation part which I'll refactor separately)
So I'm looking at a sensible way of DRYing my app:
At the moment I have something like this.
public FirstBuilder(string line, int lineNumber, bool output, string subjectType, string inquiryCode)
{
var split = Regex.Split(line, #"\|");
if (split.Count() != SPLIT_COUNT)
throw new Exception("This does not appear to be a valid First Type input file.");
_lineNumber = lineNumber;
_reportId = output ? TXT_REPORT_ID : XML_REPORT_ID;
_subjectType = subjectType;
_responseType = output ? TXT_RESPONSE_TYPE : XML_REPONSE_TYPE;
_inquiryCode = inquiryCode;
_product = split[0];
_number = split[1];
_amount = split[2];
_currency = split[3];
_name = split[4];
_nationalId = split[5];
_gender = split[6];
_dateOfBirth = split[7];
_nationality = split[8];
}
public XElement RequestElement
{
get
{
return new XElement("REQUEST",
new XAttribute("REQUEST_ID", _lineNumber),
RequestParametersElement,
SearchParametersElement);
}
}
private XElement RequestParametersElement
{
get
{
return new XElement("REQUEST_PARAMETERS",
ReportParametersElement,
InquiryPurposeElement,
ApplicationElement);
}
}
private XElement ReportParametersElement
{
get
{
return new XElement("REPORT_PARAMETERS",
new XAttribute("REPORT_ID", _reportId),
new XAttribute("SUBJECT_TYPE", _subjectType),
new XAttribute("RESPONSE_TYPE", _responseType));
}
}
etc. etc...
//used by
var x = new FirstBuilder(x,y,z,etc.).RequestElement();
This all works and is very fast...but SecondBuilder also uses these same elements, along with some different ones.
So I'm looking at the "best" way to refactor these out:
Shared Abstract class with inheritance?
Shared "Helper" classes?
Extension methods to return "built" elements?
Classes per element that extend XElement?
My suspicion is that this will balloon from the two examples as a quick solution to around 30 in then next month!
THX.
I would refactor the private properties to methods that receive the required values as input parameters. You can then move them into a PartsBuilder class and use that one in you concrete builders.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
There has been talk of Enums in general violating Clean Code-principles, so I'm looking for people's favorite Enum anti-patterns and alternative solutions for these.
For example I've seen code like this:
switch(enumValue) {
case myEnum.Value1:
// ...
break;
case myEnum.Value2:
// ...
break;
}
It's one step better than switch-statements with magic strings, but this probably could have been solved better with a factory, a container or other pattern.
Or even old-school code like this:
if(enumValue == myEnum.Value1) {
// ...
} else if (enumValue == myEnum.Value2) {
// ...
}
What other anti-patterns and better implementations have you experienced with enums?
I think Enums are quite useful. I've written a few extensions for Enum that have added even more value to its use
First, there's the Description extension method
public static class EnumExtensions
{
public static string Description(this Enum value)
{
var entries = value.ToString().Split(ENUM_SEPERATOR_CHARACTER);
var description = new string[entries.Length];
for (var i = 0; i < entries.Length; i++)
{
var fieldInfo = value.GetType().GetField(entries[i].Trim());
var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
description[i] = (attributes.Length > 0) ? attributes[0].Description : entries[i].Trim();
}
return String.Join(", ", description);
}
private const char ENUM_SEPERATOR_CHARACTER = ',';
}
This will allow me to define en enum like this:
public enum MeasurementUnitType
{
[Description("px")]
Pixels = 0,
[Description("em")]
Em = 1,
[Description("%")]
Percent = 2,
[Description("pt")]
Points = 3
}
And get the label by doing this: var myLabel = rectangle.widthunit.Description() (eliminating any need for a switch statement).
This will btw return "px" if rectangle.widthunit = MeasurementUnitType.Pixels or it will return "px,em" if rectangle.widthunit = MeasurementUnitType.Pixels | MeasurementUnitType.Em.
Then, there is a
public static IEnumerable<int> GetIntBasedEnumMembers(Type #enum)
{
foreach (FieldInfo fi in #enum.GetFields(BindingFlags.Public | BindingFlags.Static))
yield return (int)fi.GetRawConstantValue();
}
Which will let me traverse any enum with int based values and return the int values themselves.
I find these to be very useful in an allready useful concept.
It all depends what your trying to do with the enum.
If you are trying to stop your developers from passing magic numbers into your operations and you want to keep the data referential integrity intact with your DB then, YES! Use T4-Templates (using your ORM) to go to your MeasurementUnitTypes table and generate a enum with the ID, Name and Description columns matching the enum’ int, Enum_Name and Description Attribute (nice approach for additional field\data to enum #danijels) as suggested above. If you add a new Measurement Type to your MeasurementUnitTypes table you can just right click and run the T4-Template and the enum code is generated for that new row added in the table. I don’t like hard-coded data in my application that doesnt link to my DB hence the mention of the T4-Template approach. It is not extensible otherwise...what if some other external system wants to retrieve our Measurement Criteria used in our system, then it is hard-coded in the system and you can't expose it to the client via a service. That left there.
If the purpose is not data related and you have some logic assigned to a specific enum then NO! this violates the SOLID (Open close principle) as you would somewhere in your application apply a switch or bunch of Ifs to action the logic per enum, ALSO if you did it REALLY bad these switches or Ifs are all over the show....good luck adding a new enum... so it is not open for extension and closed for modification as you need to modify existing code, as per the SOLID principle.
If your choice is 2 then I suggest then to replace your enum with the following using the example from #danijels comment:
public interface IMeasurementUnitType
{
int ID { get; }
string Description { get; }
// Just added to simulate a action needed in the system
string GetPrintMessage(int size);
}
The above code defines the interface (code contract) that each measurement should adhere to. Now lets define Percentage and Pixel measurement :
public class PixelsMeasurementUnitType : IMeasurementUnitType
{
public int ID => 1;
public string Description => "Pixel";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} pixels of the total screen size";
}
}
public class PercentMeasurementUnitType : IMeasurementUnitType
{
public int ID => 2;
public string Description => "Persentage";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} persent of total screen size (100)";
}
}
So wee have defined two types, we would use them in code as follows:
var listOfMeasurmentTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(IMeasurementUnitType).IsAssignableFrom(p)
&& !p.IsInterface)
.ToList();
Here we grab all the TYPES that extends the IMeasurementUnitType interface and NOT the interface itself. Now we can use the Activator to create instances of the classes to populate our UI controls:
public IEnumerable<IMeasurementUnitType> GetInstantiatedClassesFromTypes(List<Type> types)
{
foreach (var type in types)
{
yield return (IMeasurementUnitType)Activator.CreateInstance(type);
}
}
You can change the code above to be generic for any type, AND NOW life happens and the client give a new measuring unit type called Point as a new requirement, I don't need to CHANGE ANY code, just add the new type (extend the code NOT modify). The new type will automatically be picked up in the application.
public class PointMeasurementUnitType : IMeasurementUnitType
{
public int ID => 3;
public string Description => "Point";
public string GetPrintMessage(int size)
{
return $"This is a {Description} Measurement that is equal to {size} points of total screen size";
}
}
a Good idea would be to cache your types for performance benefits upon starting your application or try and use a DI container of your choice.
Also, one can argue that somewhere in you application you would need to distinguish between types and I agree, however you want to keep apples with apples. So try as far as possible to apply the same principle used for this types. If this type is used in some sort of Graphics processor (for example) class then have a IGraphicsProcessor and have your concrete classes that differentiate between these types for example PersentageAndPixelGraphicsProcessor (that extends from IGraphicsProcessor) or if it distinguishes only one type call it PersentageGraphicsProcessor.
Sorry for the HUGE SA but I really like enum's however I feel when you trying to separate logic using a enums it is a STRONG anti-pattern.
comments welcome,
This isn't an answer, as much as contributing to a list of Enum anti-patterns.
During a code review this morning, I ran into a case similar to the following, all in the same class.
Two cases:
Before drinking
After drinking
..
public enum ListEnum
{
CategoryOne,
CategoryTwo,
CategoryThree,
CategoryFour
}
public class UIELementType
{
public const string FactoryDomain = "FactoryDomain";
public const string Attributes = "Attributes";
}
Using enums in not anti-pattern. In some books about refactoring this code is used to demonstrate how to replace it with polymorphism. It would be OK when you overuse enums in code.
I see having two switch statements as a symptom of non-OO design as explained further in this answer.