Where to define constants and use them anywhere? - c#

In Java I would write something like
public interface ICar {
static String RED_CAR = "/res/vehicles/car_red.png";
static String BLUE_CAR = "/res/vehicles/car_blue.png";
static String GREEN_CAR = "/res/vehicles/car_green.png";
}
Because C# doesn't allow using fields in interface, where do I define this constants in C#, when I wish to use them more than once?

You can define a static class to contain your constants (which need to be public as by default fields without modifier are private):
public static class Car
{
public const string RED_CAR = "/res/vehicles/car_red.png";
public const string BLUE_CAR = "/res/vehicles/car_blue.png";
public const string GREEN_CAR = "/res/vehicles/car_green.png";
}
After this you can use constants like Car.RED_CAR.

If all your constants are files it's better to include them in your resources.
In your project properties there's a resource section, vs can create a Resources.resx if you need one.
In there you can add all sorts of files or strings (for translations mostly).
You can then access them through Properties.Resources.RED_CAR
I would not name them like that though. It's from the time when all variables where globals and naming conventions like that where needed to know what was stored in the variable. But when accessing your data like this it's always clear what's going on.

Related

Best way to display Global Resource Value

I've got a Global Resource file with many values
Currently in code I call the value like this
TxtSuccess.Text = (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
But if later in the design we needed to rename variables then maintaining will be a pain.
would it be better to do something like this?
public class AppGlobalConstants
{
public string MsgSuccess{ get; private set; }
public AppGlobalConstants()
{
MsgSuccess= (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
}
}
Then if later on the team wanted to change the name of some of these global resources they could do so without having to modify any pages which used these resources.
We want to use globals as there are plans for our web application (asp.net web forms 4.5) to be available to additional countries and languages in the future.
I would rather do something like this:
public static class AppGlobalConstants
{
public static string MsgSuccess
{
get
{
return (string) GetGlobalResourceObject("GlobalResource", "msgSuccess");
}
}
}
This way, the values are static. In case the name changes, you simply modify the strings in this class. Because everything is static in this class, you could do something like this:
Console.WriteLine(AppGlobalConstants.MsgSuccess);
If you want, you could also add a set accessor to the properties. Because everything is static, there's no need to create instances of this class.

How can I assign a property to an attribute

I would like to assign a property string to below attribute.
[ExtractKeyAttribute(**"Extraction"**)]
public class Extract
{
....
}
so extraction is my string but I don't want hard code into there. Any suggestions on better way to assign
You can't do this.
Attribute values must be constant expressions. The values are baked into the compiled code. If you don't want to use a constant expression, you can't use an attribute... and you possibly shouldn't. It may mean you're using attributes when you should be using a different approach.
You might want to read Eric Lippert's blog post on properties vs attributes.
Of course, you don't have to use a string literal there. You could have:
[ExtractKey(ExtractionKeys.Extraction)]
...
public static class ExtractionKeys
{
public const string Extraction = "Extraction";
}
... but it's still a compile-time constant.
In your comments you say you have all (string) values in a static class. Is your static class a class with readonly properties? I mean, do the values change? If not, replace some of those properties in your static class with const strings values. U can use these values to set your attribute.
So...
static class MyClass
{
public string MyValue {get;}
}
would become:
static class MyClass
{
public const string MyValue= "MyValue";
}
Now your attribute can be set as follows:
[ExtractKey(MyClass.MyValue)]
If you want to modify the property of your attribute during runtime, then you can do this with this code:
ExtractKeyAttribute myAttribute = typeof(Extract).GetCustomAttributes(typeof(ExtractKeyAttribute), false)[0] as ExtractKeyAttribute;
myAttribute.MyValue = "MyRunTimeValue";

Exposing common values from a custom structure/type

One of my projects has a value type/struct that represents a custom identifier string for a video format. In this case, it's going to contain a content type string, but that can vary.
I've used a struct so it can be strongly type when it's passed around, and perform some sanity checks on the initial string value.
public struct VideoFormat {
private string contentType;
public VideoFormat(string contentType) {
this.contentType = contentType;
}
public string ContentType {
get { return this.contentType; }
}
public override string ToString() {
return this.contentType;
}
// various static methods for implicit conversion to/from strings, and comparisons
}
As there are a few very common formats, I've exposed these as static read only fields with default values.
public static readonly VideoFormat Unknown = new VideoFormat(string.Empty);
public static readonly VideoFormat JPEG = new VideoFormat("image/jpeg");
public static readonly VideoFormat H264 = new VideoFormat("video/h264");
Is it better to expose the common values as static read only fields or as get only properties? what if I want to change them later? I see both methods used throughout the .Net framework, e.g. System.Drawing.Color uses static readonly properties while System.String has a static read only field for String.Empty, and System.Int32 has a const for MinValue.
(Mostly copied from this question but with a more specific and not directly related question.)
Properties are a good idea unless you are declaring something that never changes.
With properties you can change the inside implementation without affecting programs consuming your library and handle changes / variations. Consuming programs wont break and wont require to be recompiled.
e.g. (I know this is a bad example but you get the idea..)
public static VideoFormat H264Format
{
get{
// This if statement can be added in the future without breaking other programs.
if(SupportsNewerFormat)
return VideoFormat.H265;
return VideoFormat.H264;
}
}
Also keep in mind that if you decided to change a field to a property in the future, consuming code breaks.

Accessing Global Session Key in Umbraco

I have a group of session keys which I declare in a Global class file, these get set properly upon login.
public static class SessionKeys
{
public static string memberToken = "token";
public static string memberFirstName = "first_name";
public static string role_pmn = "PMNInstructor";
public static string role_superUser = "";
public static string role_chapterAdmin = "ChapterMember";
public static string role_registeredUser = "RegisteredUser";
}
I have a need to later access some of these session vars in an XSLT Macro for navigation. I'm having trouble finding the correct syntax for accessing these variables in the XSLT Macro.
This syntax works in my .NET Macros:
Session[Globals.SessionKeys.role_pmn]
The correct syntax should be
umbraco.library:Session
This link should provide more information.
Alternatively, you could create an extension library, get the reference in .net, and then just reference your library in the xslt (umbraco.tv video for reference, or text-only instructions)
Syntax for accessing the global session keys in XSLT is different than what is used to access them in C#. You merely have to use the string value you set the key to.
umbraco.library:Session(PMNInstructor)

Why can a class not have a static or constant property and an instance property of the same name?

I've never really questioned this before until now. I've got an input model with a number of fields, I wanted to present the string names of the properties through the input model so that my Grid can use them:
public class SomeGridRow
{
public string Code { get;set; }
public string Description { get;set; }
public const string Code = "Code";
}
Obviously, this gives the error:
The type 'SomeGridRow' already
contains a definition for 'Code'
Why can the CLR not cope with two properties of the same name which are, in my eyes, separate?
string code = gridRow.Code; // Actual member from instantiated class
string codeField = SomeGridRow.Code; // Static/Const
I'm now just using a child class called Fields within my inputs now, so I can use SomeGridRow.Fields.Code. It's a bit messy, but it works.
Because you can also access static (or, non-instance in this case) properties in the same way (inside the same class), and it would be a bit confusing, for example:
public class SomeGridRow
{
public string Code { get;set; }
public const string Code = "Code";
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
Because both this:
public class SomeGridRow
{
public string Code { get;set; }
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
And this:
public class SomeGridRow
{
public const string Code = "Code";
public void MyMethod() {
var thing = Code; //what would this reference?
}
}
are valid ways to access properties, static or not. It doesn't answer the "why can't I?" question, but more of the why it's not allowed...it would be far too ambiguous IMO.
It probably could, but the designers of C# wanted to avoid ambiguities that can come from such use (abuse?) of language features.
Such code would end up being confusing and ambiguous to users (did I want the instance or the static method call?, Which one is right?).
In addition to the points already made about ambiguity, i would say that the naming needs to be relooked in such a case.
If two variables / fields having the exact same name in the same context i.e class but different values to me sounds more like a naming issue.
If they are exactly same, you dont need 2 fields.
If they are slightly different, you should have more accurate names.
In some other languages with a similar syntax, one can access a static member through an instance. So you could access both string.Empty and "abc".Empty.
C# doesn't allow this (though it does sort of from inside the class or a derived class, in that you can omit the class name for a static member and can omit this for an instance member), primarily to avoid confusion (I find it more handy than confusion tbh, but that's just me, I like switch fall-through too so what do I know).
Having introduced a stricter rule to allow for less ambiguity, it would be counterproductive to allow a new looser rule on the back of it that allowed for more. Think how many "why must I use this with property X but not property Y?" questions SO would have if it was allowed (we'd have to force this with property X to be clear we meant the instance member).

Categories