Reputation: 8188
When I am looking at my code and I am writing things like..
if (role == "Customer")
{
bCustomer = true;
}
else if (role == "Branch")
{
bIsBranch = true;
}
Or
foreach(DataRow as row in myDataSet.Tables[0].Rows)
{
row["someField"]=somefield.Tostring()
}
Are you guys doing this? When is this ok to do and when shouldn't you be doing this? What if any would be a better approach to write this if any?
Thanks For the Comments: I guess I should add what if (for this example purposes) I am only using this role comparison once? Is it still a better idea to make a whole new class? Also should I have 1 class called "constants" are multiple classes that that hold specific constants, like "roles" class for example?
Upvotes: 15
Views: 23368
Reputation: 1235
nameof
expressionUsing the nameof
expression, you can retrieve the literal casing of types
, classes
, structs
, properties
, methods
, functions
, fields
, arguments
, parameters
, locals
, and more to the casing they appear in the code at compile time. This will not eliminate or solve all your "magic string" problems, but its a good start and worth discussing.
For example, getting the literal casing of an enum
value.
public enum ExportType
{
CSV,
Excel
}
nameof
Usagenameof(ExportType.CSV); // "CSV"
nameof(ExportType.Excel); // "Excel"
nameof(ExportType); // "ExportType"
Returns the literal casing of the expression in the argument.
If you are referring the code names of specific type names
, classes
, etc.
, strongly consider replacing those fragile magic strings with nameof
. You will not fear changing the name of a internal type, or property without fear of breaking the code. Using renaming features IDEs like Visual Studio has will rename all references anywhere in your code base referring to that expression.
This operation is done at compile time. Ultimately, if you are relying on the names of types
, classes
, etc.
in your code, you can introduce compile time type safety via nameof
expression into your code when referring to them.
You can eliminate a lot of reflection in your code as well that gets the names of these objects or types.
Getting the name of generic types
nameof(T); // "T"
nameof(TEntity); // "TEntity"
In these cases, you must continue to use reflection to get the name of the type at runtime. typeof(T).Name
.
For example:
var enumValuesNames = typeof(ExportType).GetProperties().Select(p => p.Name).ToArray();
Upvotes: 2
Reputation: 1758
For the sake of maintainability, you should formalize string comparators when possible, either as named constants or as an enumeration. The benefit for the programmer is that you can localize changes. Even when using a refactoring tool, finding all the places a string is used can be tedious and error prone. You may only have one place where you're doing this comparison today, but you or a future maintainer may extend this to other parts of the code. Also, the class itself may grow and need to be broken apart. These things tend to creep up on a program over time.
I would simply declare these strings as constants close to where they're used, but together. Don't bother with a new abstraction like Roles until you know you need it. If the number of roles you need to compare grows, or is needed outside of this class, then you can create a Roles enum or Roles class, depending on the complexity of the comparison.
Also, by using constants, you signal the intended use to the compiler, so you get some minor memory management benefits, which, given your comparison is in a loop, is generally a good practice.
Upvotes: 0
Reputation: 3799
I believe a better approach is to use application settings which means you won't ever need to recompile your code if "Customer" or "Branch" values change. Magic values are obviously bad, and this would be a good first step/option getting away from them. Additionally it keeps your values in one place, and I also believe you can reload the settings at runtime without restarting the application (although I haven't tried this myself).
E.g.:
if (role == Properties.Settings.Default.CustomerRole)
{
bCustomer = true;
}
else if (role == Properties.Settings.Default.BranchRole)
{
bIsBranch = true;
}
Upvotes: 2
Reputation: 5719
Polimorphism is one thing, but using hardcoded strings along your code is not good at all. It's way better to define a variable holding the string and use this variable along the code. This case if you need to change something (believe me you will), you can just change the value of this variable and it's done (less errors too!)
Upvotes: 0
Reputation: 82614
I would make a Roles static class:
public sealed class Roles
{
public const string BRANCH = "Branch";
public const string CUSTOMER = "Customer";
public static bool IsCustomer(string role)
{
return role == CUSTOMER;
}
}
Then in your code:
bCustomer = Roles.IsCustomer(role);
Alternatively, this requires a little more setup but the RoleProvder (depending on Web or Not) provides a lot of good methods.
Upvotes: 2
Reputation: 43087
No. Don't use "magic strings". Instead create a static class with constants, or an enum if you can.
For example:
public static class Roles
{
public const string Customer = "Customer";
public const string Branch = "Branch";
}
Usage:
if (role == Roles.Customer)
{
}
else if (role == Roles.Branch)
{
}
Here's a good discussion on various solutions.
Upvotes: 36
Reputation: 30097
It is always better to declare the hard coded strings separately as constants rather then declaring a new string every time. It keeps code clean and reduce errors which are caused by typing mistakes.
Regarding should or shouldn't be done totally depends on scenario.
Upvotes: 3
Reputation: 7778
Well, in my opinion it is up to you and it depends on your application design. I uaully look at it from the positive side- if application works the way it supposed to work, it is all good. IMHO
Upvotes: -1