someone wants me to make other people's code compliant to some FxCop ruleset which includes rule CA1726:Use preferred terms. Most of the terms/replacements are all right and I can understand that one has to decide on one single way to name things.
However, what's the deal with the term 'flags'? Can anyone explain to me why I shall not use this name? (before I go and complain about it at my boss ;) )
Say, I have a data object which has a member of class 'flags' which bundles a large number of properties that define how to handle the data object. How else would you call this?
In the book Framework Design Guidelines, which is what FxCop is based on, the authors say that using Flag or Flags is a bad idea. Their alternative suggestion is that when naming enumerations that you use a singular name for standard enums and a plural name for bit field (flags) enums.
For example if you wanted to create an enum listing different visibilities then you would name it Visibilities instead of VisibilityFlags or Visibility:
[Flags]
public enum Visibilities {
Public,
Private
}
The only items considered flags in .NET by the authors are these bitfield enumerations due to the keyword Flags attribute.
I would say that the property should be named aptly, and that the term Flags characterises the property rather than describing it.
Flag or Flags | There is no replacement term. Do not use.
For instance, Flags is generally used with enumerations (that are decorated with the appropriate attribute) and we certainly don't need to explicitly state so within the name / identifier of a property:
[Flags]
enum StorageMode
{
None = 0,
Next = 1,
...
Last = 32
}
class StorableItem
{
public StorageMode StorageMode { get; set; }
}
But, in your case, I get the feeling that whatever is named, or contains within its name, Flags, isn't actually a set of flags in the above sense - which just brings up another reason as to why to avoid it.
Related
So far I have soemthing like this:
public enum MyEnum
{
[Display(Name="FirstElement")]
element1 = 1,
[Display(Name="SecondElement")]
element2 = 2
}
And in the view, if I use:
Html.EnumDropDownListFor(x=>x.EnumProperty)
While having:
public MyEnum EnumProperty {get;set;}
On the view model, the dropdown works as expected(I see FirstElement, and the value attached is element1)
The problem is that I want to have a dash in the value, like this:
public enum MyEnum
{
[Display(Name="FirstElement")]
element1 = 1,
[Display(Name="SecondElement")]
element2 = 2,
[Display(Name="Third")]
element-dashed = 3
}
It won't work, as element-dashed is not a valid entry.
This won't work either:
[Value("element-dashed")]
[Display(Name="Third")]
elementDashed = 3
The answer to your question is simple. But it warrants an explanation, to explain why this is the answer.
There is no functional reason to want a dash in an enum.
Let's say I have a working application, which contains your enum:
public enum MyEnum
{
[Display(Name="FirstElement")]
element1 = 1,
[Display(Name="SecondElement")]
element2 = 2
}
Suppose I change the enumerator names:
public enum MyEnum
{
[Display(Name="FirstElement")]
BatmanIsBruceWayne = 1,
[Display(Name="SecondElement")]
SupermanIsClarkKent = 2
}
I am assuming that every usage of the enum in code is also adjusted accordingly. If you use the Rename method in VS (F2), this is automatically the case.
Nothing has changed about how the application works. Functionally speaking, the name of an enum does not matter.
public enum CardSuit { Hearts, Spades, Diamonds, Clubs }
public enum CardSuit { TheRedOne, TheBlackOne, TheOtherRedOne, TheOtherBlackOne }
Of course, the first one is much more readable for developers than the second one. However, a compiler does not care about the meaning of the enum names. It only cares that the appropriate value is used consistently.
This is the same principle as variable names. While we should of course take care to make variable names readable by developers; there is no technical reason (i.e. to the functionality of the application) why we should use int myDescriptiveInteger over int x.
We only choose a descriptive name for the purposes of readability for humans who maintain the code.
There is a single exception to this: If you are calling .ToString() on an enum, in order to have a string representation of the field you are using.
Note: While this is technically possible and has been done before by others; I do wonder if that's really what you should be doing here. You're already assigning explicit int values to the enum values. Those int values are much easier for saving/loading an enum instead of trying to work with its string equivalent. While both are technically possible, using the int is far better due to a smaller footprint and a lack of the naming problem that you are wrongly trying to fix here.
It is not clear from your question whether this is the case for you. Maybe it's done somewhere in your application, maybe it's not. I can't know that without you telling me.
If it is not done, then your problem is functionally irrelevant. The name does not matter except for readability purposes, and I'm quite convinced that your developers won't suddenly stop understanding the intent of the code because there's a dash missing.
If it is done, then you actually have already provided the answer to your problem. Instead of calling .ToString() on the enum; instead you must use the value of [Display(Name="FirstElement")] as the correct "string name" for your enum.
public static string GetName(this myEnum enumValue)
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.GetCustomAttribute<DisplayAttribute>()
.GetName();
}
And then you can change the following code:
myEnumValue.ToString();
To the following code, which correctly uses the attribute's value instead of the enum field name:
myEnumValue.GetName();
In both cases, the core answer remains the same: You do not need to worry about the specific name of your enum fields because it is functionally irrelevant.
Edit If you want your enum value to be displayed differently in the combobox than you want it to be when you save the value, then use a second attribute to differentiate between the two. But the principle still stands: do not base yourself off of the field names than an enum uses.
And I would like to stress again that you should be using the integer values of your enum. I see no reason why you would explicitly assign int values to your enum and then refuse to use them.
I am lately starting a project and I have a question.
Let's say I am dealing with a class Person, and a person can have one(or more) deseases he is encountering.
so I have created an enum :
public enum diseases{headache,throat,bruise,gunshot,none}; // enum containing all the diseases
public diseases disease;
And further in code I set a certain disease to that person and it works fine.
Thing is, there might be a point in my project where a person might have 2 diseases.
So there are my questions:
Is using enum the best option here? I want my code to be organized and understood and that's a main reason for using enums.
If using enum is a good option, I have managed to combine this enum with bit-flags(using [System.Flags]) so when time comes I can check for a disease that contains two different values from the enum. is this a good approach?
If using enum is a good option, should I just create a second property from diseases (just like I created disease) and save all the trouble from using bit-flags?
Thanks in advance for any light on that matter, couldn't figure what was the best approach here.
A good option would to make a List<diseases> to hold for a single person.
public class Person
{
public string Name { get; set; }
public List<diseases> Diseases { get; set; }
public Person(string name)
{
this.Name = name;
Diseases = new List<diseases>();
}
}
This way you can enumerate over all the values relatively easily without having to worry about flags.
For example:
var bob = new Person("bob");
bob.Diseases.Add(diseases.gunshot);
var hasHeadache = bob.Diseases.Any(x => x == diseases.headache);
An enum is a plausible (yet a bit simplistic) way to represent one disease.
If someone may have N diseases, then just use a container of objects of that type, such as a list. But you need to choose the right container. A list of diseases may be, for example: { headache, throat, headache, throat, gunshot }. Lists allow duplicates. Whay you may actually need is a set of diseases. A set is a structure which does not allow duplicates.
The choice of how you represent one disease and the fact that a person may have N diseases, so that you need a person to have a container of diseases, are two totally independent facts.
Use the FlagsAttribute on your enum.
[Flags]
Public enum diseases
{
// your values here
}
This should give you what you need.
There is a lot of opinion being asked for here and the right answer is that it depends on a lot of variables what solution is right in any given situation. You CAN use an ENUM to represent multiple values so long as the [Flags] attribute is given to the ENUM. Keep in mind that if you decide to go that route then you are responsible for assigning the values of the ENUM specific non-overlapping values like 1, 2, 4, 8, 16, 32, etc.
Is using enum the best option here? - This depends on how many diseases you would like to cover. If the number is small (10..20) and the list is flat (no hierarchy of diseases) then you are fine. Otherwise, consider some alternative.
is [System.Flags] a good approach? - Yes, in case of a small, flat, list [System.Flags] approach is very good and extremely efficient.
Should I just create a second property from diseases and save all the trouble from using bit-flags? Having a second property in place of running a collection is a terrible idea. If you have to do something twice, chances are, you'd do it N times. Make a collection or bit fields, never go for a second property unless the system is inherently limited to two items (say, a binary tree).
If the list of diseases is not "flat" (e.g. you plan to have ViralThroat, BacterialThroat, and ThroatInjury in place of a simple throat that you have now) you would be better off modeling diseases as classes, and creating a collection of diseases attached to a Person. You could add methods for checking the collection for particular diseases, which could be smart about the search: for example, find any kind of throat sub-disease when a throat is passed as a search criterion.
enum is just one of many perfectly acceptable options here. Others include OO solutions such as base/derived classes, or simple lists of string (or event lists of enums, why not?!). Often the simplest approach is best. We would have to know a lot more about your problem to recommend one over the other.
While using Flags is one solution, I would not recommend it in this case. Flags are not verbose on what they are for. Any time I used flags, I would have to re-learn how to properly work with flags when I needed to modify my code. One simple alternative is creating a property for each possible disease...
public class Diseases
{
public bool Headache {get;set;}
...
public bool HasAnyDisease() { return Headache || Throat || ...;}
}
But that has it's downsides as well. It's not easily extensible. I would recommend using the Decorator Pattern. Each disease could decorate the class which may make future interactions with it easier to maintain. If you need to have variance disease combinations cause different outcomes, this may be better in the long run.
I'm trying to enhance my enum so I've tried a suggestion on Display and another one on Description.
I'm annoyed because I don't understand the difference between them. Both Description class and Display class are from framework 4.5.
It's additionally annoying since neither of them work in the code. I'm testing the following but I only get to see the donkeys...
[Flags]
public enum Donkeys
{
[Display(Name = "Monkey 1")]
Donkey1 = 0,
[Description("Monkey 2")]
Donkey2 = 1
}
Neither of these attributes have any effect on the enum's ToString() method, which is what gets called if you just try to insert it into a Razor template. ToString() always uses the name declared in code -- Donkey1 and Donkey2 in your case. To my knowledge, there's no built-in way to specify an alternate string representation for the enum to use automatically.
I assume there are (at least) two reasons for that:
Serialization. ToString() uses the name so that Enum.Parse() can parse it back into the enum.
Localization. .NET was designed with global audiences firmly in mind, and if you want a human-readable string representation of an enum, it's extremely unlikely that there will be just one string representation, at which point it's going to be up to your application to figure out how to do it.
If you know your app will never be translated to other languages, or if you just want a string representation you can use in debug output, you're welcome to use an attribute (either one from the Framework, or one you declare yourself) to define a string representation for each enum value, and write some utility functions to do the string conversion. But you can't make the enum's ToString() do it for you (since that would break serialization); you'd have to write your own code to do it.
However, since you're writing a Web app, there's a fair chance that you will have a global audience -- in which case you'll need to localize your enum strings the same way you localize all your other text.
In order to protect ourself from failure because of any renaming of properties (Let's say you regenerate your poco classes because you have changed some column names in the relevant Db table) is it a good practice to decalre constant strings that keep the property names inside?
public const string StudentCountPropertyName = "StudentCount";
public int StudentCount {get;set;}
For example: Think about a DataBinding; where you type the property name in the DataFieldName attribute explicitly.
Or this is not a good idea and there is a better and still safer way?
It is always a good idea IMHO to move any 'magic strings' to constants.
You could consider using lambda expressions to 'pick' your properties, for example:
GetDataFieldName(studentCollection => studentCollection.Count)
You will have to implement GetDataFieldName yourself, using a bit of reflection. You can look at HtmlHelperExtensions from MVC to see how it can be done. This will be the most safe approach, which gives you compile-time errors when something goes wrong and allows easy property renaming using existing refactoring tools.
From one point of view: if you using this property name multiple times it is good practice. It will help for sure with the refactoring and when you for example change property name you see that you need change this const also.
From another point of view i guess it will be ugly when my class with 10 properties will have 10 additional consts. Another solution if you want avoid consts or explicit name typing can be getting property names through the reflection.
Use such approach or not you should decide yourself.
I think it's a common practice to put this "magical string" or "magical numbers" in some kind of strong typed store.
Something you can consider is to code it in a Aspect Orientied Way.
For example the calls to notifypropertychagned can be realized with an attribute implemented with an aop framework, like PostSharp .
[NotifyChange]
public int Value {get;private set}
This tools also have some downsides but i think there are scenarios where they can save you a lot of work
I do not know if I fully understand your question, but if I understand it right I would have used an attribute for that, an example could be the use of ColumnAttribute in Linq which you use to map a property to a specific column in a database (http://msdn.microsoft.com/en-us/library/system.data.linq.mapping.columnattribute.dbtype.aspx), like in this example:
[Column(Storage="ProductID", DbType="VarChar(150)", CanBeNull=False)]
public string Id { get; set; }
And I would never use DataFieldName, I would DataBind to the strongly typed objects (and of course also make an interface to the class that uses the property above so I easily can change the implementation in the future ;))
I suppose if the names are used in many places then it would be easier just to change them in this one place and use the constant as described in your comment.
However, a change to a database column name and object property name implies a change to your conceptual data model. How often do you think this is going to happen? In the early stages of a project, whilst conceptual modelling and implementation are paralellised across a dev team, this may be quite fluid, but once the initial conceptual modelling is done (whether this in a formalised conscious manner or just organically), it's usually quite unlikely that fundamental things like these are going to change. For this reason I think it's relatively unusual to have do this and the technique will only be productive in edge cases.
Absolutely. It's a good idea.
By the way, I would argue that these kind of things could be better stored in application settings, because you can define such things in an application configuration file later by overriding these settings.
Doing that this way you'll avoid re-compiling if some database, POCO or whatever changes, and as in newer Visual Studio versions like 2010, you can tell it to generate settings with "public" accessibility, you can share strongly-typed settings with any assembly that reference the one containing them.
At the end of the day, I'd change your code with DataBindingSettings.StudentCountPropertyName instead of a constant.
Easy to manage, more re-usable, and readable, as "you configure a data-binding with its settings".
Check this MSDN article to learn more about application settings:
http://msdn.microsoft.com/en-us/library/a65txexh(v=VS.100).aspx
I really don't know much about attributes in general in C#, I've seen them in use in a lot of different ways/places but I don't think I see the importance of some of them. Some definitely have importance because they provide a noticeable function, such as [Serializable]. Yet, others don't seem so important, such as one my coworker uses to mark properties with [DataMember].
I suppose my question is, what are attributes and how are they useful? Is there a way to create my own attributes and how can I tell if fields/methods/classes/whatever have particular attributes or what values are set in those attributes?
what are attributes?
Attributes enable you to embed information about a type or method in the metadata which describes that type or method.
You typically want to use attributes to describe facts about the mechanism of the type or method rather than the meaning of the type or method. For example, suppose you have a type Employee. A fact about the meaning of Employee is that it is a kind of Person, that an Employee has a Manager, and so on. A fact about the mechanism of Employee is that it can be the target of data binding, or it can be serialized to disk, or whatever. An employee cannot be serialized to disk, but the class Employee can be. Attributes let you separate information about the technical details from the semantic model.
Is there a way to create my own attributes?
Yes. Create a class which extends Attribute. By convention you want to name it "FooAttribute". If you do so you can use either the [Foo] syntax or the [FooAttribute] syntax at your discretion.
How can I tell if fields/methods/classes/whatever have particular attributes or what values are set in those attributes?
Use the GetCustomAttributes method on the reflection objects.
Where should I read for more information?
Start with the attributes tutorial:
http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx
And then read all of chapter 17 of the C# specification.
Attributes are a means by which you can associate metadata with types in .NET. This allows you to check for a type and get information about it that's separate from the "runtime" information of the type.
This can be very useful. You mentioned [Serializable], but other simple examples include many of the System.ComponentModel types, such as Description, which is used by the property grid to "describe" properties when you work with them in the designer. Since the "description" of a property isn't really related to the behavior of the type in a program (at runtime), it doesn't belong in the class. However, it's very handy when you go to edit a control in a visual designer, for example, to see a description (or category, etc) of a property. Attributes are the means by which this is handled.
I think the answer to the following question will provide you some insight to your questions.
How do attribute classes work?
Here is a repost of the answer I provided.
Attributes are essentially meta data that can be attached to various pieces of your code. This meta data can then be interogate and affect the behaviour of certain opperations.
Attributes can be applied to almost every aspect of your code. For example, attributes can be associated at the Assembly level, like the AssemblyVersion and AssemblyFileVersion attributes, which govern the version numbers associated with the assembly.
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Then the Serializable attribute for example can be applied to a type declaration to flag the type as supporting serialization. In fact this attribute has special meaning within the CLR and is actually stored as a special directive directly on the type in the IL, this is optimized to be stored as a bit flag which can be processed much more efficiently, there are a few attributes on this nature, which are known as pseudo custom attributes.
Still other attributes can be applied to methods, properties, fields, enums, return values etc. You can get an idea of the possible targets an attribute can be applied to by looking at this link
http://msdn.microsoft.com/en-us/library/system.attributetargets(VS.90).aspx
Further to this, you can define your own custom attributes which can then be applied to the applicable targets that your attributes are intended for. Then at runtime your code could reflect on the values contained in the custom attributes and take appropriate actions.
For a rather naive example, and this is just for the sake of example :)
You might want to write a persistence engine that will automatically map Classes to tables in your database and map the properties of the Class to table columns. You could start with defining two custom attributes
TableMappingAttribute
ColumnMappingAttribute
Which you can then apply to your classes, as an example we have a Person class
[TableMapping("People")]
public class Person
{
[ColumnMapping("fname")]
public string FirstName {get; set;}
[ColumnMapping("lname")]
public string LastName {get; set;}
}
When this compiles, other than the fact that the compiler emits the additional meta data defined by the custom attributes, little else is impacted. However you can now write a PersistanceManager that can dynamically inspect the attributes of an instance of the Person class and insert the data into the People table, mapping the data in the FirstName property to the fname column and the LastName property to the lname column.
As to your question regarding the instances of the attributes, the instance of the attribute is not created for each instance of your Class. All instances of People will share the same instance of the TableMappingAttribute and ColumnMappingAttributes. In fact, the attribute instances are only created when you actually query for the attributes the first time.
C# provides a mechanism for defining declarative tags, called attributes, which you can place on certain entities in your source code to specify additional information. The information that attributes contain can be retrieved at run time through reflection. You can use predefined attributes or you can define your own custom attributes.
http://msdn.microsoft.com/en-us/library/aa288059%28v=VS.71%29.aspx