I'm doing some interop and need to pass some GUID's. Is there a way to add a GUID attribute to an enum value and when it is marshalled it has the appropriate value?
Basically I'm trying to convert the code
#if !defined( STATIC_KSDATAFORMAT_SUBTYPE_PCM )
#define STATIC_KSDATAFORMAT_SUBTYPE_PCM\
DEFINE_WAVEFORMATEX_GUID(WAVE_FORMAT_PCM)
DEFINE_GUIDSTRUCT("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM);
#define KSDATAFORMAT_SUBTYPE_PCM DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_PCM)
#endif
(and several other similar ones)
and use them in an enum so I can specify the appropriate subtype format easily. Obviously I could probably just use a dictionary or some other similar method but I would like to make it as transparent as possible.
It would be nice to do something like
enum MyGuids : Guid
{
Guid1 = GUID("...") or just "..."
}
I can use a class/struct instead
static class MyGuids
{
public static Guid flag1 = new Guid("9ED54F84-A89D-4fcd-A854-44251E925F09");
}
But the only problem here is there is no way to relate the Guid in unmanaged structure to this class. It's specified as Guid and if I replaced it with MyGuids then it won't be a Guid any more. e.g., I lose type safety since any guid can end up in the field and not just the ones from MyGuid.
Any ideas?
Guids are structures in .NET, they are too large to fit in a simple value type by a factor of two. Sounds to me that you need a structure member initialized. That's going to need an assignment statement in your code. The const will work just fine for this. There is otherwise no way to get the compiler to do it automatically.
var sound = new foo();
sound.waveFormat = MyGuids.flag1;
// etc..
How about something like this?
void Main()
{
var dog = MyValues.Dog.ToId();
var cat = MyValues.Cat.ToId();
var bird = MyValues.Bird.ToId();
}
public enum MyValues
{
Dog,
Cat,
Bird
}
public static class Functions
{
public static Guid ToId(this MyValues value)
{
switch (value)
{
case MyValues.Dog:
return Guid.Parse("6d139d6a-2bfa-466d-a9a5-c6e82f9abf51");
case MyValues.Cat:
return Guid.Parse("AA139d6a-2bfa-466d-a9a5-c6e82f9abf51");
case MyValues.Bird:
return Guid.Parse("BB139d6a-2bfa-466d-a9a5-c6e82f9abf51");
default:
throw new InvalidDataException();
}
}
}
Related
This is probably an incredibly dumb question but: I have a function that takes in a string, and I want to make sure that the string is a constant from a specific class. Essentially the effect I'm looking for is what enums do:
enum MyEnum {...}
void doStuff(MyEnum constValue) {...}
Except with strings:
static class MyFakeStringEnum {
public const string Value1 = "value1";
public const string Value2 = "value2";
}
// Ideally:
void doStuff(MyFakeStringEnum constValue) {...}
// Reality:
void doStuff(string constValue) {...}
I know this can technically be achieved by doing some thing like
public static class MyFakeStringEnum {
public struct StringEnumValue {
public string Value { get; private set; }
public StringEnumValue(string v) { Value = v; }
}
public static readonly StringEnumValue Value1 = new StringEnumValue("value1");
public static readonly StringEnumValue Value2 = new StringEnumValue("value2");
}
void doStuff(MyFakeStringEnum.StringEnumValue constValue) {...}
But it feels kind of overkill to make an object for just storing one single value.
Is this something doable without the extra code layer and overhead?
Edit: While a enum can indeed be used for a string, I'd like to avoid it for several reasons:
The string values may not always be a 1:1 translation from the enum. If I have a space in there, different capitalization, a different character set/language, etc. I'd have to transform the enum in every function where I want to use it. It might not be a lot of overhead or a performance hit in any way, but it still should be avoided--especially when it means that I'm always mutating something that should be constant.
Even if I use a separate string array map to solve the above function, I would still have to access the translations instead of just being able to use the enum directly. A map would also mean having two sources for the same data.
I'm interested in this concept for different data types, ex. floats, ulongs, etc. that cannot be easily represented by enum names or stored as an enum value.
As for string -> enum, the point of using an enum in the first place for me is that I can rely on intellisense to give me a constant that exists; I don't want to wait until compile time or runtime to find out. Passing in an actual string would be duck typing and that's something I definitely don't want to do in a strongly typed language.
I would suggest you create an enum and parse the string value into an enum member.
You can use the Enum.Parse method to do that. It throws ArgumentException if the provided value is not a valid member.
using System;
class Program
{
enum MyEnum
{
FirstValue,
SecondValue,
ThirdValue,
FourthValue
}
public static void doStuff(string constValue)
{
var parsedValue = Enum.Parse(typeof(MyEnum), constValue);
Console.WriteLine($"Type: { parsedValue.GetType() }, value: { parsedValue }");
}
static void Main(string[] args)
{
doStuff("FirstValue"); // Runs
doStuff("FirstValuesss"); // Throws ArgumentException
}
}
I have an enum on helper library in my solution.
For example
public enum MyEnum
{
First,
Second
}
I want to use MyEnum in a few another project. I want to decorate this enum in each project with own attribute like this:
public enum MyEnum
{
[MyAttribute(param)]
First,
[MyAttribute(param2)]
Second
}
How to decorate enum from another library with own local attribute?
You can't do what you've described - the best you can do is to create a new Enum that uses the same set of values. You will then need to cast to the "real" enum whenever you use it.
You could use T4 templates or similar to generate the attributed enum for you - it would be much safer that way as it would be very easy to map the wrong values, making for some very subtle bugs!
Linqpad Query
enum PrimaryColor
{
Red,
Blue,
Green
}
enum AttributedPrimaryColor
{
[MyAttribute]
Red = PrimaryColor.Red,
[MyAttribute]
Blue = PrimaryColor.Blue,
[MyAttribute]
Green = PrimaryColor.Green
}
static void PrintColor(PrimaryColor color)
{
Console.WriteLine(color);
}
void Main()
{
// We have to perform a cast to PrimaryColor here.
// As they both have the same base type (int in this case)
// this cast will be fine.
PrintColor((PrimaryColor)AttributedPrimaryColor.Red);
}
Attributes are compile-time additions (metadata) to code. You can not modify them when using the compiled code assembly.
(Or perhaps you could if you are a diehard low-level IL wizard, but I certainly am not...)
If your enum values require modification or parameters at various places, then you should consider other solutions, e.g. a Dictionary or even a Database Table.
E.g. using a Dictionary:
var values = new Dictionary<MyEnum, int>()
{
{ MyEnum.First, 25 },
{ MyEnum.Second, 42 }
};
var valueForSecond = values[MyEnum.Second]; // returns 42
You can do something like this, but it will be tedious.
The idea is to use your project settings to allow the change when you import the enum in a new project.
First, you will need 2 attributes:
// This one is to indicate the format of the keys in your settings
public class EnumAttribute : Attribute
{
public EnumAttribute(string key)
{
Key = key;
}
public string Key { get; }
}
// This one is to give an id to your enum field
[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : Attribute
{
public EnumValueAttribute(int id)
{
Id = id;
}
public int Id { get; }
}
Then, this method:
// This method will get your attribute value from your enum value
public object GetEnumAttributeValue<TEnum>(TEnum value)
{
var enumAttribute = (EnumAttribute)typeof(TEnum)
.GetCustomAttributes(typeof(EnumAttribute), false)
.First();
var valueAttribute = (EnumValueAttribute)typeof(TEnum).GetMember(value.ToString())
.First()
.GetCustomAttributes(typeof(EnumValueAttribute), false)
.First();
return Settings.Default[String.Format(enumAttribute.Key, valueAttribute.Id)];
}
I did not check if the type is correct, not even if it finds any attributes. You will have to do it, otherwise you will get an exception if you don't provide the right type.
Now, your enum will look like that:
[Enum("Key{0}")]
public enum MyEnum
{
[EnumValue(0)] First,
[EnumValue(1)] Second
}
Finally, in your project settings, you will have to add as many lines as the number of members in your enum.
You will have to name each line with the same pattern as the parameter given to EnumAttribute. Here, it's "Key{0}", so:
Key0: Your first value
Key1: Your second value
etc...
Like this, you only have to change your settings values (NOT THE KEY) to import your enum and change your attributes to a project to another.
Usage:
/*Wherever you put your method*/.GetEnumAttributeValue(MyEnum.First);
It will return you "Your first value".
I am a C++ programmer moving to C# (so complete newb really). So far its a pretty easy transition :)
I am porting some code (well, re-writing it) from C++ to C#. I am stuck with lots of possibilities on how to port the following C++ STL structures. Here is a C++ code snippet of my C++ structure layout (I have not bothered showing the enums to save on clutter, but I can add if required):
struct DeviceConnection_t
{
DeviceType_e device;
DeviceState_e state;
bool isPass;
DeviceConnection_t() :
device(DEV_TYPE_UNKNOWN),
state(DEV_STATE_DISCONNECTED),
isPass(false)
{}
};
struct Given_t
{
std::string text;
std::vector<DeviceConnection_t> deviceConnections;
};
struct Action_t
{
ActionEventType_e type;
uint32_t repeat_interval;
uint32_t repeat_duration;
DeviceType_e device;
bool isDone;
Action_t() :
type(AE_TYPE_UNKNOWN),
repeat_interval(0),
repeat_duration(0),
device(DEV_TYPE_UNKNOWN),
isDone(false)
{}
};
struct When_t
{
std::string text;
std::multimap<uint32_t, Action_t> actions; // time, action
};
So here I have a vector of DeviceConnection_t, which I have read here: c-sharp-equivalent-of-c-vector-with-contiguous-memory can just be made into a C# List<DeviceConnection_t>. That seems to work, so far so good.
Next is my multimap<int, Action_t> where the int is a time value where duplicate entries are expected/allowed.
I read here: multimap-in-net that there is no equivalent in C#, but there are various implementations out there.
So I could use one of these, but other questions I read like: order-list-by-date-and-time-in-string-format got me thinking there might be a better way to achieve what I want.
What I really want is:
1.A list of Action_t in time order - where time could be an element of Action_t (I removed it as a element in my c++ because it became my multi-map key). I also need to be able to search through the collection to find time values.
2. Some sort of default constructor to populate the default values of a newly instantiated struct, but I can't see how this is done either.
I really like the look of the Dictionary C# class, but I don't think that fits any of my requirements at the moment (might be wrong here).
So my two questions are:
What is the best way to create a time ordered collection of objects?
How can I assign default values to a new instance of a structure? (in the same way a default constructor does in C++)?
By using struct, it is impossible to enforce initial values. No explicit default constructor can be provided and in case of default construction, all values will be initialized with their default value. It is only possible to provide additional constructors, where fields can be initialized. In the example, if AE_TYPE_UNKNOWN and DEV_TYPE_UNKNOWN would be 0, then default initialization would actually be equivalent to your values.
struct Action_t
{
// example constructor, but there will always be a default constructor
public Action_t(ActionEventType_e type, DeviceType_e device)
{
this.type = type;
this.device = device;
this.isDone = false;
this.repeat_interval = 0;
this.repeat_duration = 0;
}
public ActionEventType_e type;
public UInt32 repeat_interval;
public UInt32 repeat_duration;
public DeviceType_e device;
public bool isDone;
}
If you need to enforce initialization with values that differ from the default, then you need to create a class, where explicit initialization is possible.
class Action_t
{
public ActionEventType_e type = ActionEventType_e.AE_TYPE_UNKNOWN;
public UInt32 repeat_interval = 0;
public UInt32 repeat_duration = 0;
public DeviceType_e device = DeviceType_e.DEV_TYPE_UNKNOWN;
public bool isDone = false;
}
However, for more flexibility I'd advice to use public properties, either as auto properties or as public properties with private backing field. Depending on your choice and used language standard version, you have different options how to write the properties and the initialization:
class Action_t
{
public Action_t()
{
repeat_interval = 0;
}
public UInt32 repeat_interval { get; set; }
private UInt32 _repeat_duration = 0;
public UInt32 repeat_duration
{
get { return _repeat_duration; }
set { _repeat_duration = value; }
}
public bool isDone { get; set; } = false; // valid for C# 6
}
You should read into the differences between struct and class in C#, since there are some mayor differences that you may not expect as a C++ programmer, where struct is basically a public-default class. Then decide, if struct is suited for your case.
The best equivalent to a sorted multimap would probably be a SortedDictionary<key, ICollection<values>> with an add method that handles new keys / adding to existing keys.
IDictionary<DateTime, ICollection<Action_t>> actions = new SortedDictionary<DateTime, ICollection<Action_t>>();
void AddAction(DateTime key, Action_t action)
{
ICollection<Action_t> values;
if (!actions.TryGetValue(key, out values))
{
values = new List<Action_t>();
actions[key] = values;
}
values.Add(action);
}
Unfortunately C# doesn't seem to have a sorted List. The Dictionary is fine if you have Key, Value pairs.
1) If its just a collection (List) you can take a look at the discussion here:
Is there a SortedList<T> class in .NET?. Otherwise you can manually sort the collection(I named it sort in my example) like:
actions.Sort((x, y) => x.time.CompareTo(y.time));
In this your time object should be a IComparable or a primitive, but you can replace "x.time.CompareTo" to any other sorting method. (Based on: List<> OrderBy Alphabetical Order).
If you use a list you can just search the collection with linq:
actions.First(x=>x.time.certainValue == DesiredValue);
But there are many functions to search through the tree. There are some displayed: https://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods(v=vs.110).aspx
2) There are multiple ways to do this. First off, the default constructor:
Action_t() {
type=AE_TYPE_UNKNOWN;
repeat_interval=0;
repeat_duration=0;
device= DEV_TYPE_UNKNOWN);
isDone = false;
}
This works like any other code. But if all values are public Properties (Also a variable: https://msdn.microsoft.com/nl-nl/library/x9fsa0sw.aspx) then you can remove the constructor (or have a public one that you can access) and create new instances with:
new Action_t {
type=AE_TYPE_UNKNOWN,
repeat_interval=0,
repeat_duration=0,
device= DEV_TYPE_UNKNOWN),
isDone = false
}
The difference is where the variables are set. The default constructor is always safe.
I hope this answers your question!
In C# I know we can't we assign objects to an Enum. The functionality I'm after is when an Enum is declared, it triggers off an event.
So instead of having
enum MyEnum
{
string, int, etc
}
I could have
enum MyEnum
{
classType1, classType2
}
This would then also allow the classes classType1/classType2 constructor to be called which could (for example) be useful for logging for when the enum is declared.
Another way of presenting my issue could be
enum MyEnum
{
string1
{
//logic
},
string2
{
//logic
}
}
Is there a work around for this?
Instead of enum you can use a static class with static properties, it can be used same as an enum but you can write code inside getter and setter.
U could use properties instead of enum (then u can write ur own logic which will be called after/before assigning the variable). The enum structure should be used to create flags-like stuff.
private string _myVar;
public string MyVar
{
get { return _myVar; }
set
{
// logic 1 here
_myVar = value;
// logic 2 here
}
}
No work around as, I think, your expectation does not match the language. For example consider what would happen with:
if (myEnumValue == MyEnum.classType1)
Your question implies that on the right a class of 'classType1' would be instantiated for the equality test and then the result would depend on that types implementation of equality. This is confusing when the item on the left is an enum ... but with your assumption it is an object of type 'classType1' which implies that both the left and right are temporary objects.
You can see that this could not work.
But ... what I think your really after is a factory to create objects from an enum. Whole other question that raised other questions (sorry). An enum like this implies a state ... so if you have a state why does that state need an enum? A big question in itself, check out the state pattern.
Hope I've helped.
An enum is a Value type based on an Int## type. So this is the same as asking: can I get some logic into the assignment of int i = 7; and the direct answer is No.
Neither can you base an enum on anything other than an integer type.
But your requirement seems to be with tracking instances. That's easy with properties. But you can only do it for a specific property, not build it into the Type.
Enums are barely integers with comprehensive labels. As far as I know, what you are looking for cannot be done using enums.
However, and as stated by #Grumbler85, this behavior can be simulated using factories.
A factory is a special type of object that are used to create instances of other objects.
The easiest way to implement a factory is using a switch statement but other ways exists (reflection for example). Here's a simple example of what you are looking for:
Class A
{
...
}
Class B
{
...
}
enum eKnownTypes
{
A,
B
}
Class Factory
{
/*
Implement Singleton here
....
*/
public object CreateInstance(eKnownTypes t)
{
/*
Raise any event needed here
...
*/
switch (t):
{
case eKnownTypes.A: return new A(); break;
case eKnownTypes.B: return new B(); break;
}
return null;
}
}
/*
Set Event Handlers here
Factory.Instance.CustomEvent += new EventHandler ...
....
*/
A objectA = Factory.Instance.CreateInstance(eKnownTypes.A) as A;
...
You can do it with an enum, but you could do
public struct MyType
{
public const int OneValue = 1;
public const int TwoValue = 2;
private static readonly MyType one = new MyType(OneValue);
private static readonly MyType two = new MyType(TwoValue);
private readonly value int;
private MyType(int value)
{
this.value = value;
}
public static One
{
get { return this.one; }
}
public static Two
{
get { return this.two; }
}
public static implicit operator int(MyType source)
{
return source.value;
}
}
To give you a class that behaves like an enum but is fully extendable.
for instance, you can do
var myType = MyType.One;
switch (myType)
{
case MyType.OneValue:
...
case MyType.TwoValue:
...
default:
...
}
The instances are immutable and can be accuarately tested for equality using the implemenation inhereted from object, i.e. reference quality.
OK, so I have a database field of type char(1) that has a small number of possible state codes (e.g. 'F'= Failure, 'U'=Unknown, etc.). I'd like to have a C# enum class that corresponds to these states. I can do:
public enum StatusCode : byte {
Unknown = (byte) 'U',
Failure = (byte) 'F',
// etc.
}
So far so good. But in the DataTable returned from the database, the column values are System.Data.SqlTypes.SqlString instances. There are obviously some issues converting from a C# string (or even a C# char) to a C# byte (since C# char is really a UTF-16 codepoint). But in this case I know the values are constrained to a small set, and the code should throw an exception if a value outside this set comes through.
With that in mind, what's the best way of doing this? Is it safe to cast from a SqlString to a byte? Would Convert.ToByte() be better? Would it be better to simply use a switch/case construct to crosswalk the values into the enum?
I'm looking for the "best" way to do this, not only in terms of getting the right results but also for code clarity. I suppose I could also just use some constants like
public const char UnknownStatus = 'U';
public const char FailureStatus = 'F';
But I'd rather use an enum if possible. Any thoughts?
Edit: To clarify what I want do do with this, I'm expecting to use these values frequently throughout my code. For example, I want to be able to do things like:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus) {
case StatusCode.Unknown:
// do something
break;
}
}
And so forth. I particularly want to avoid things like:
public void DoSomething(char currentStatus) {
if(currentStatus == 'F') {
// do something
}
}
Since in this case I'm using what amounts to "magic numbers" all over the place. In particular, this would make migrating to some other state-flagging system virtually impossible. Does that make sense?
Maybe a "constant" object?
public sealed class StatusCode {
private char value;
public static readonly StatusCode Unknown = new StatusCode('U');
public static readonly StatusCode Failure = new StatusCode('F');
private StatusCode(char v) {
value = v;
}
public override string ToString() {
return value.ToString();
}
}
Then, later in your code, you could use it like an enum: StatusCode.Unknown. You could also provide an internal method to 'parse' a received value into an object of StatusCode.
Skip to edit Have you tried this (which doesn't work as you've checked and commented):
public enum StatusCode : char
{
Failure = 'F',
Unknown = 'U',
...
}
EDIT - correct solution
or this (maybe even try with a struct):
public sealed class StatusCode
{
public static readonly char Failure = 'F';
public static readonly char Unknown = 'U';
...
public char Value { get; set; }
}
your code you provided would work like this:
public void DoSomething(StatusCode currentStatus) {
if(currentStatus.Value == StatusCode.Failure) {
throw new SomeException();
}
switch(currentStatus.Value) {
case StatusCode.Unknown:
// do something
break;
}
}
If you don't like to use Value property you can always implement implicit equality operator between StatusCode and char types. In that case, your code wouldn't change a bit.
If you're on .NET 2.0 and higher, you could implement this using a generic dictionary:
Dictionary<char,string> statusCode = new Dictionary<char,string>();
statusCode.Add('U', "Unknown");
statusCode.Add('F', "Failure");
or alternatively:
Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>();
statusCode.Add('U', StatusCode.Unknown);
statusCode.Add('F', StatusCode.Failure);
and you could access the string representation for a given code like so:
string value = statusCode['A'];
or
StatusCode myCode = statusCode['A'];
and so on. You would have to fill that dictionary from the database values, or from some kind of a config file or something.
Marc
Would something like this work for you?
public Enum StatusCode : int{
[StringValue("U")]
Unknown =0,
[StringValue["F"]
Failuer=1
}
If you have a table called StatusCode which includes an integer primary key then you could use that as your identifier as well as hook it into your logic. And in that case, the enum would be the best thing to use. Though i'm not sure if this is feasible for you.
One option is to setup your enum with identical names to the values in your database, such as:
enum StatusCode
{
/// <summary>Unknown</summary>
U = 0,
/// <summary>Failure</summary>
F,
/// <summary>Etc</summary>
E
}
Then use a static method to convert char values to an enumerated value
private StatusCode CharToEnum(string statusCodeChar)
{
foreach (FieldInfo fi in typeof(StatusCode).GetFields())
{
if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null);
}
return StatusCode.U;
}
Short and sweet my man.. Does everything you need it to. You shouldn't need to use enum because you don't need it to assign an internal value to your possible states, you already know the values to your states.
public sealed class StatusCode
{
public const string Unknown= "U";
public const string Failure= "F";
public const string Success= "S";
}