Is it possible to declare a constant Guid in C#?
I understand that I can declare a static readonly Guid, but is there a syntax that allows me to write const Guid?
No. The const modifier only applies to "primitive" types (bool, int, float, double, long, decimal, short, byte) and strings. Basically anything you can declare as a literal.
Declare it as static readonly Guid rather than const Guid
public static readonly Guid Users = new Guid("5C60F693-BEF5-E011-A485-80EE7300C695");
and that's that.
While you can't seem to do that you can do that to be parsed whenever you need it:
const string _myGuidStr = "e6b86ea3-6479-48a2-b8d4-54bd6cbbdbc5";
But don't use the above guid as it belongs to me solely, I first generated it so I claim ownership on this particular guid above! But I'm generious - use this one instead (I don't like how it talks back to me but it's a nice guid overall when it keeps its mouth shut): 284c694d-d9cc-446b-9701-b391876c8394
I am doing it like this:
public static class RecordTypeIds
{
public const string USERS_TYPEID = "5C60F693-BEF5-E011-A485-80EE7300C695";
public static Guid Users { get { return new Guid(EntityTypeIds.USERS_TYPEID); } }
}
Depends on what you want a const for.
If you want to have a known GUID that you can reuse as needed, the above solution of storing the GUID as a string and parsing to GUID as needed works.
If you need a default parameter value, that won't work. The alternative is to use a nullable Guid and use null as your constant value.
public void Foo(string aParameter, Guid? anOptionalGuid = null)
Related
Is there any alternative present for Static Field in C# as static field never garbage collected?
If I want to declaure the number of strings, constants which I want to use throughout the program, I am finding a way for that.
You can use a const but it has to be a value.
public class Foo
{
public const string Bar = "Bar";
}
See https://msdn.microsoft.com/en-us/library/e6w8fe1b.aspx
As an addition to Richard Schneiders answer, sometimes you can't use const (the compiler should know the const value at the compiling time), but want to provide constant like behaviour. In that case readonly is the choice:
public class Foo {
// Settings should be read and then preserved intact
public static readonly String Settings = File.ReadAllText(#"C:\MySettings.txt");
...
}
You can Use Const for this.
Const is a reserved word. It allows us to specify that a value is invariant and must not be modified after compile-time. Const values, like const strings, help us simplify and optimize programs.
Eg:
public static class Constants
{
public const string Name = "abc";
}
https://msdn.microsoft.com/en-us/library/acdd6hb7.aspx
I would like to know how to declare a "global" variable for a class. That is I want that this variable is available everywhere just in this class and not in the other classes.
What is the best form to declare them? or when do I use each of these forms?
I would like to have it OO.
1st Form:
enter code here
private const string _Column1= "Names";
private const string _Column2= "Numbers";
private const string _Column3= "Alarms";
2nd Form:
private enum enumColumnNames
{
Names, // integer value = 0
Numbers, // 1
Alarms, // 2
};
3rd Form:
internal sealed class clsColumnNames
{
public static readonly clsColumnNames Column1 = new clsColumnNames("Names");
public static readonly clsColumnNames Column2 = new clsColumnNames("Numbers");
public static readonly clsColumnNames Column3 = new clsColumnNames("Alarms");
private clsColumnNames(string value)
{ Value = value;
}
public string Value { get; private set; }
}
4th Form:
internal sealed class clsColumnNames
{
public static readonly string Column1 = "Names";
public static readonly string Column2= "Numbers";
public static readonly string Column3= "Alarms";
}
Thanks!
Cis
private enum enumColumnNames
{
Names, // integer value = 0
Numbers, // 1
Alarms, // 2
};
And as long as the string value is equal to the enum name you can use
enumColumnNames.Names.ToString() will produce "Names"
static class ColumnNames
{
public const string Names = "Names";
public const string Number = "Numbers";
public const string Alarms = "Alarms";
}
Since these are constants, I would recommend the enum approach. As mentioned by Amorphis, this will aloow you to get the literal value viw .ToString(). This also allows you to pass around your strings as a parameter boxed to the given values by using the enum type as a parameter, rather than a string which may or may not be one of the given values. There are some ways around this (such as converting an out-of-range int) but it's still less error-prone than passing raw strings everywhere.
Not also, however, that whenever you have front-facing text, you should use a Resource (.resx), because this allows you to adjust how the strings show up depending on the language settings of the machine running your code. If any of these strings are ever to be seen by a user, use resources!
The 1st form is the best for the following reasons:
Simplest
Less typing
The 2nd form will just result in lots of needless extra code/typing (i.e., enumColumnNames.Names.ToString(), just to get the value of your variable. I've already worn my fingers out just typing that once).
For the 3rd form, let's break it down:
Making the class internal isn't really changing anything since your variables are private
Making the class sealed just means the class cannot be inherited from; again, this is not changing anything since your variables are private
Making your variables static just means that they won't show up in an object of the class; again, not really doing anything
Making your variables readonly just means that they can only be set in a constructor
There is no point in having a property for a variable that you intend to be constant; Properties are generally used to make sure that a variable is being set/gotten properly
And for the 4th form, same gripes as with the 3rd, just minus the last gripe.
EDIT:
Since these particular variables you are asking about are supposed to be column names, I would actually recommend Amorphis' answer (sorry Amorphis, I don't have enough rep to upvote your answer just yet). If your global variables are unrelated to each other (i.e., a variable for the name of a webpage vs. a variable for the number of characters allowed in a text field are nice and dissimilar), then you ought to use the first form.
I am trying to generate a constant value that I will be using like following:
public class Foo()
{
public const String ExtensionKey = Guid.NewGuid().ToString();
public int ID { get; set; }
}
The compiler is throwing an error:
The expression being assigned to 'Foo.ExtensionKey' must be constant
I know that it is not possible to execute a method (a constructor or a type initializer) at compile time. I am looking for a workaround to get randomly generated Guid assigned to different ExtensionKey constants of different classes.
EDIT:
The intention is to generate a UNIQUE Guid per type. The Guid value must be the same for all objects instances and whenever the application run. This is the behavior of Const and I am looking for a way to respect it.
(Much of this answer "promoted" from a comment to the question.)
In Visual Studio, you can choose "Tools" - "Create GUID". Or in Windows PowerShell you can say [Guid]::NewGuid().ToString(). That will give you a Guid. Then you can make the string representation of that particular Guid your string constant.
public const string ExtensionKey = "2f07b447-f1ba-418b-8065-5571567e63f6";
The Guid is fixed, of course. A field marked const is always static (but you must not supply the static keyword; it is implied).
If you want to have the field of Guid type, then it can't be declared const in C#. Then you would do:
public static readonly Guid ExtensionKey = new Guid("2f07b447-f1ba-418b-8065-5571567e63f6");
readonly means that the field can only be changed from a (static in this case) constructor of the same class (a constructor of a derived class is not OK).
Call to Guid.NewGuid() will return you a new GUID every time, this is why you get an exception. You can replace const with readonly or static or use a fixed GUID string with const.
public class Foo
{
// Fixed "forever" or until you manually change it
// Cannot be changed in run-time
public const String ExtensionKey = "3c88c196-06ec-4a89-bffa-6f3fd221f425";
// You will get a new GUID per each Application Domain and per each run
// Can be changed
public static String ExtensionKey1 = Guid.NewGuid().ToString();
// By convention this shall be private, as it's a field
// You will get a new GUID per each instance of a class,
// Once assigned, the value cannot be changed
public readonly String ExtensionKey3 = Guid.NewGuid().ToString();
// You will get a new GUID per each Application Domain and per each run,
// Once assigned, the value cannot be changed
public static readonly String ExtensionKey4 = Guid.NewGuid().ToString();
}
Edit
The intention is to generate a UNIQUE Guid per type. The Guid value
must be the same for all objects instances and whenever the
application run.
Generate a new GUID manually and use the first option
// Fixed "forever" or until you manually change it
// Cannot be changed in run-time
public const String ExtensionKey = "3c88c196-06ec-4a89-bffa-6f3fd221f425";
You can get almost the same behavior by replacing const with static readonly
public static readonly String ExtensionKey = Guid.NewGuid().ToString();
This question lacks a bit of details; do you want your GUID to be unique per class and process, or unique per class, but the same every time you start your program? It's two very different things.
If you want a unique GUID per class and process then you have some valid answers already, but if you want a unique GUID per class, but not per process, then you need some other way of solving your problem. Either you enter a GUID in your code, or you use some kind of GUID generator that uses some text as input instead of some random number generator based on the clock or similar.
I would suggest reading this blog post about generating a GUID from a string, the actual code resides on GitHub.
By using something like that and using the full name of the class as input you will get a unique GUID per class, but still the same for every process
I just want don't use "Managers" for each attribute and use some enum for that.
But it seems it is impossible or I am wrong?
So I try to replace
[RequiresRole("Managers")]
with
[RequiresRole(HardCodedRoles.Managers.ToString())]
...
public enum HardCodedRoles
{
Administrators,
Managers
}
How about a class instead of an enum, making the class static to avoid somebody new:ing it ?
public static class HardCodedRoles
{
public const string Managers = "Managers";
public const string Administrators = "Administrators";
}
[RequiresRole(HardCodedRoles.Managers)]
You could also use the nameof keyword, i.e.:
[RequiresRole(nameof(HardCodedRoles.Managers))]
The reason you see the error is because ToString() is a method and thus the value cannot be calculated at compile time.
If you can use [RequiresRole(HardCodedRoles.Managers)] instead, you can perform the ToString elsewhere in your code, and this could give you the functionality you need. This will require that you change the parameter of your attribute from string to HardCodedRoles.
(I would imagine that using a const won't work, because the type of the parameter will still be string, so the input won't be restricted.)
How can I use a static Guid as argument in an attribute?
static class X
{
public static readonly Guid XyId = new Guid("---");
}
[MyAttribute(X.XyId)] // does not work
public class myClass
{
}
It does not work because Guid must be readonly, it can not be const. The string and byte[] representation would also be readonly.
Is there any workaround for this?
It's not possible and will never be possible, because [Attributes] are compiled as metadata and static variables are initialized at runtime, and of course the former cannot access the latter (except via Reflection).
If the standard
public const string MyGuid = "blah";
won't work for you, then AFAIK the only way to achieve what you want, is with Reflection.
Unfortunately there is no a good way to pass Guid to attribute.
Only workaround would be to use another type for that and convert it to Guid.