0

I am a C# junior programmer and running into a requirement of defining a lot of constant integers in my program (up to 5000 of them). I would like to know whether doing something like this in my C# program file

const int a=1;
const int b=2;
....
const int x5000=5000;

is practical in a business application. My supervisor tells me to leave them in a separate file then initialize a variable to store them when the program starts to run. But I find that method is no good because any user can change the file. I don't know if there is any better way to do this. I also think all of constant things are still apparent in a compiled C# file even when I view it with notepad. I would want all of the readable text in source files after compiled into a pe to be hexificated.

wonea
  • 4,783
  • 17
  • 86
  • 139
  • 7
    Why do you need 5000 constants? Seems something wrong in your design to me. – Patrick Hofman Feb 21 '17 at 08:04
  • 1
    Maybe stick them in a database? – Paul Andrew Feb 21 '17 at 08:04
  • 2
    @PatrickHofman maybe is working with PLC and It has 5k return code, weird I know but possible. WebJanitor: what about enum? – Tinwor Feb 21 '17 at 08:06
  • Thank you for your quick replies, 5000 is an exaggerated number I made up, only around 4000. – Janette Vlasicia Feb 21 '17 at 08:09
  • ...Or maybe multiple enums if you have different groups of values (like errors, warnings, ect') – Zohar Peled Feb 21 '17 at 08:09
  • @webjunior well that makes a world of difference... ;-) – Zohar Peled Feb 21 '17 at 08:10
  • does the constant should be always editable without recompiling? if no, put them in another `.cs` file.. – Bagus Tesa Feb 21 '17 at 08:10
  • I don't really get your problem. Is it that you have to type 5k items by hand? Why not make a script or a linq pad miniprogram to do it for you? Also what's the deal with storing in a separate file? Do you mean with that that they are not actual constants but vales read from a file during runtime? – Balázs Feb 21 '17 at 08:10
  • 3
    @WebJanitor Oh, it's _only_ 4000? That changes everything, then. No need to answer Patrick's question in that case. /s – JLRishe Feb 21 '17 at 08:11
  • 3
    I'd suspect that this is blind adherence to the "no magic numbers" rule taken to its illogical extreme. In the domain in which you're working, do you genuinely believe that there are over 4000 non-changing (or slowly changing, slower than the rate of releases) variables? – Damien_The_Unbeliever Feb 21 '17 at 08:20
  • 2
    '*I also think all of constant things are still apparent in a compiled C# file even when I view it with notepad.*' of course they are, how would you use them if they arent present; what's wrong with that? '*I would want all of the readable text in source files after compiled into a pe to be hexificated.*' I don't see your problem here either; it feels like you're taking worries about inept users fiddling with the program a step too far. Also converting ints to hex won't do a thing in terms of security because anyone with necessary hacking skills wont have problems with reading hex values. – Balázs Feb 21 '17 at 08:22

3 Answers3

2

A common method of handling this is to declare classes that holds your constant values and gives them meaningful names.

With thousands of constants it may be useful to use more than one class if the constants can be grouped meaningfully, usually around how they are used.

public class Constants
{
    public int A { return 1; }
    public int B { return 2; }
    public int X5000 { return x5000; }
}

These classes are then passed into any class that needs the constants they hold.

Additionally, if desired, the class can be initialized with the values from an external source during construction.

The main point is to give the constants meaningful names, group by use and abstract away where the values are coming from.

David Culp
  • 5,354
  • 3
  • 24
  • 32
  • 1
    This is exactly an answer I was going to post ;-) – Paweł Hemperek Feb 21 '17 at 08:28
  • 2
    I don't fully agree with this answer: 1) if they are true constants, they should be public const *fields* for performance purposes, since getters actually get compiled into method calls. This does not violate encapsulation as long as they are indeed constant values so they are not subject to changing. There is a reason `Math.Pi` and `Math.e` does that. 2) If they aren't, they still should be static. – Balázs Feb 21 '17 at 08:29
  • The values, or even the class, can be made static and retain much of the value. But, I would resist doing so since it cannot then be injected where needed creating an unnecessary hard dependency. – David Culp Feb 21 '17 at 08:32
  • I don't see why you would ever want to inject a constant value holder that does nothing else. You don't inject enums either and this situation is pretty much the same apart from the fact that with your solution you can use, for example, strings as well. I wouldn't consider directly referencing it as creating a hard dependency, or any sort of dependency for that matter. Also, there isn't even any gain I can think of, since even with unit testing you would want to get the values from the actual constant holder and not from a dummy. If you had to fake it even tests would become a maintenance hell – Balázs Feb 21 '17 at 08:35
  • Constants rarely are truly constant, but are usually derived or assigned based on some business criteria. You will notice the example of `Math` you presented has just the two constants, `PI` and `E`, and not the hundreds (thousands?) of constants used in math. Most of what is considered constant is constant only within the business case it is being used -- business cases change. **It is a good practice to inject business values into classes so it is clear what business considerations it depends on.** – David Culp Feb 21 '17 at 08:43
  • I agree with that but I'm still not convinced; there is no way of telling without knowing the actual nature of the 'constants' he has to define. I simply cannot imagine 5k possible values that have to do anything with any business case, so I am left at the thought someone made in the comment section that they are error codes or such things. Since he didn't clarify it just wrote random names it is just speculating. – Balázs Feb 21 '17 at 08:53
  • seal the class for better protection. – kiran Feb 21 '17 at 12:45
  • I just cannot get why this should be the answer, can someone enlighten me? What if all value needs to offset +1 in order to become error code for new business? If you haven't plan ahead, there is a lot of overhead in changing these codes. In my experience, I faced these requests often. – Gordon Feb 22 '17 at 07:54
  • the likelihood of change is exactly why this is the answer – David Culp Feb 22 '17 at 10:36
  • the likelihood of change... **at a great cost**, introduction of regression, requirements conflict..... I just don't think this should be marked as an answer, don't jam everything into 1 static class. – Gordon Feb 23 '17 at 01:58
  • If you reread my answer and earlier comments, you will see I argue not to use static classes and argue to use multiple classes when logical groupings exist. – David Culp Feb 23 '17 at 02:11
  • Static class is absolutely correct, I can't imagine initializing 5000 integers every time it is putted into use; and grouping....Never mind... My point is "inject business values into classes" should never be talking about modifying the class which contains those constants, it will be very expensive. It should mean creating a over-watching manager class to take care variations between different business. – Gordon Feb 24 '17 at 07:07
1

You may take a look at enum and add a static class, something like ErrorCodeManager to access the enum, just in cause of refactoring source of those error code

public static class Constants
{
    public static int A { get { return 1; } }
    public static int B { get { return 2; } }
    public static int C { get { return 3; } }
    public static int x5000 { get { return 5000; } }
}
public enum EConst
{
    A = 1,
    B, // <= value is 2
    C, // <= value is 3
    x5000 = 5000,
}

They both work the same way,in my opinion enum is even more readable, why using static int?

Gordon
  • 516
  • 1
  • 3
  • 13
  • How would you save integers in a enum? What if two integers collide? – Patrick Hofman Feb 21 '17 at 08:53
  • um.... the nature of enum is to avoid integers collision.... XD – Gordon Feb 22 '17 at 07:26
  • Just read those example in the enum reference, you wouldn't ask those questions. – Gordon Feb 22 '17 at 07:28
  • please post a new question instead of redirecting this one. But please post a link on this one to direct our attention. thanks. – David Culp Feb 22 '17 at 10:30
  • The real redirection here is someone proposing imaginary unknown business requirements. I'm just going back to the basic and discussing ways to handle/ refactor constant 5000 error codes. In my experience, a handful of libraries are using enum to store error code, add ErrorCodeManager/ Resolver to play with them. – Gordon Feb 23 '17 at 01:51
1

In such cases I'm trying to gather consts into logical groups. Each group - one class:

public sealed class ABCConsts{
   public const int A=1;
   public const int B=2;
   ...
}

...

public sealed class XConst{
   public const int X5000 = 5000;
}

it's better to put each class into separate file.

PS: good stuf to futher reading - Static readonly vs const fields

Community
  • 1
  • 1
Anton Semenov
  • 6,227
  • 5
  • 41
  • 69