Hi Is there a way to declare an enum or to customize the way of declaring an enum which returns an object in C#?
private enum testEnum
{
firstname =1
,lastname = 2
}
and if we want to return the names rather than 1 and 2 ?
like testEnum.firstname returns 1 .
I want to declare an enum to return objects like in Java . is it possible?
You can do this:
public class NameEnum
{
static NameEnum()
{
FirstName = new NameEnum("FirstName");
LastName = new NameEnum("LastName");
}
public static NameEnum FirstName { get; private set; }
public static NameEnum LastName { get; private set; }
private NameEnum(string name)
{
this.Name = name;
}
public string Name { get; private set; }
}
Is that close enough?
http://msdn.microsoft.com/de-de/library/system.enum.aspx
An enumeration is a set of named constants whose underlying type is any integral type except Char. If no underlying type is explicitly declared, Int32 is used. Enum is the base class for all enumerations in the .NET Framework.
You can use interfaces for this:
interface IColorEnum {};
class ColorEnum: IColorEnum
{
public static const Red = new ColorEnum();
public static const Green = new ColorEnum();
public static const Blue = new ColorEnum();
};
And use it like usual:
void foo(IColorEnum color)
{
if(color == ColorEnum.Red) {...}
}
Update+improve: you can even drop interface and just use class with couple of public static fields with type of this class and private constructor to prevent creating new instances of it:
class ColorEnum
{
private ColorEnum() {};
public static const Red = new ColorEnum();
public static const Green = new ColorEnum();
public static const Blue = new ColorEnum();
};
The docs state:
Every enumeration type has an underlying type, which can be any integral type except char.
Assuming you mean object to be complex/reference type. then the answer to your question is no. You could always create a class with named properties containing reference types.
I guess that you be a class exposing static fields that can then be of any type you want.
I think this is only possible in java.
It seems that you want to implement singleton the Joshua Bloch way.
Related
Consider the flowing code snippet
static void Main()
{
var x = new MyStruct
{
Item = new StringWrapper("abc")
};
Console.WriteLine(x.Item.PublicField);
x.Item.SetValue("xyz");
Console.WriteLine(x.Item.PublicField);
var y = new
{
Item = new StringWrapper("abc")
};
Console.WriteLine(y.Item.PublicField);
y.Item.SetValue("xyz");
Console.WriteLine(y.Item.PublicField);
}
public struct MyStruct
{
public StringWrapper Item;
}
public struct StringWrapper
{
public string PublicField;
public StringWrapper(string v)
{
PublicField = v;
}
public void SetValue(string v)
{
PublicField = v;
}
}
And the output:
abc
xyz
abc
abc
MyStruct can be declared as class, and the output will remain the same.
{abc, abc} part of output is a surprise for me, as I expect anonymous type to be converted to class or struct and behave the same.
I feel like I'm missing something obvious here and will appreciate any help.
Thanks.
The difference here is that your MyStruct (struct or class) exposes a public field while anonymous classes (new { }) expose public properties.
When you access a value type from a field or variable, you do not get a copy, you access the instance directly. Therefore making changes to it stores them in the instance.
When you instead access it via a property or method, you get a returned copy of your StringWrapper and changing that doesn't change what is stored in the anonymous classes private field.
Just to demonstrate, you can get the same behavior by making your Item field a property too:
public StringWrapper Item { get; set; }
I have created for myself several classes of the same structure - "rich enums". So it immediately suggests that it could be somehow simplified by another class I would inherit.
I wrote an example class to show you what such an enum contains:
class RichEnum
{
// ???
}
class MyEnum : RichEnum
{
// FIELDS AND CONSTRUCTOR(S)
public readonly string A;
public readonly int B;
public readonly Object C;
public MyEnum(string A, int B, Object C)
{
this.A = A;
this.B = B;
this.C = C;
}
// STATIC INSTANCES
public static readonly MyEnum Example1 = new MyEnum("string1", 1, "object1");
public static readonly MyEnum Example2 = new MyEnum("string2", 2, "object2");
public static readonly MyEnum Example3 = new MyEnum("string3", 3, "object3");
// SPECIAL INSTANCE
public static readonly MyEnum Default = new MyEnum("default", 0, "default");
// SPECIAL OBJECT FOR ITERATING OVER STATIC INSTANCES
public static readonly MyEnum[] Values = { Example1, Example2, Example3 };
// METHODS
public int GetSomeNumber()
{
return B + 10;
}
}
I have lots of various "MyEnums", but these classes all have the same structure. So they have:
Some public readonly fields (variable number) of various types
One or more constructors
Public static readonly instances
A special field used to return the value if none of those instances can match a condition. For example when I use MyEnum.Values.FirstOrDefault(...), that would return default when nothing is found
Some methods
Is there a way to create one class of this structure and then just inherit from it, making the process more simplified and less error-prone?
It seems you're reinventing the wheel: Headspring.Enumeration.
So, if your goal is just to have such a "rich" enumeration class available to you, there's a Nuget package for that; if your goal is to write your own ... well, it never hurts to look at prior art for inspiration.
If you really look at it, these classes have actually nothing in common that could be abstracted:
They have a different amount of static and non-static fields
The types of the fields are different
The values of each field differ
The names of the fields differ
The methods differ
Unless you find something they have in common, you can't create a base class. What could help you would be a code snippet that contains the general layout of such a class to speed up your typing.
Take a look at this code I posted on CodeProject a LONG time ago.
http://www.codeproject.com/Articles/13293/Descriptive-Enumerations
I won't post all the code, although it's not too bad, but here's an example of actually using it. In this case, I am trying to define an enum of a passenger's airline seat preference.
public class SeatType : DescriptiveEnum<SeatType, int>
{
public static readonly SeatType Window = new SeatType("Window Seat", 1);
public static readonly SeatType Aisle = new SeatType("Aisle Seat", 2);
public static readonly SeatType AnythingExceptSeatNearBathroom = new SeatType("Anything Except Seat Near Bathroom", 3);
private SeatType(string desc, int code)
: base(desc, code)
{
}
}
So, as you can see, that's pretty clean. Of course, you could certainly extend this to add additional methods, or include a "default", etc.
Then you can use it like this:
class Example
{
public static void Main(string[] args)
{
SeatType c = SeatType.AnythingExceptSeatNearBathroom;
Console.WriteLine(c.Description);
Console.WriteLine(SeatType.AnythingExceptSeatNearBathroom == c);
foreach (SeatType seat in SeatType.GetEnumMembers())
{
Console.WriteLine(String.Format("Seat type code: {0} - description: {1}",seat.Code,seat.Description));
}
Console.ReadLine();
}
}
The base DescriptiveEnum class also has conversion operators baked in, so it works JUST like enums do. That is, you can say:
SeatType c = (SeatType) SomeMethodThatReturnsAnInt();
I am trying to compare values that I am getting from web service, but sometimes I get int value, sometimes i get string. So it would be great that i could only check for Type.value1.
for example:
enum Type { value1 = 1 , value1="one"}
and like that for more value2, etc...
But of course, I cannot do this because it I cannot add two definitons for value1.
Sometimes a type that behaves mostly like an enum but has some richer behaviour can be very useful:
public sealed class MyFakeEnum {
private MyFakeEnum(int value, string description) {
Value = value;
Description = description;
}
public int Value { get; private set; }
public string Description { get; private set; }
// Probably add equality and GetHashCode implementations too.
public readonly static MyFakeEnum Value1 = new MyFakeEnum(1, "value1");
public readonly static MyFakeEnum Value2 = new MyFakeEnum(2, "value2");
}
You can consider adding attributes to the enums and use reflection.
enum Type
{
[Description("One")]
value1 = 1
}
I also make use of using decorating the enum with a description attribute as described by BSoD_ZA. But I would suggest that you then implement an extension method for the enumeration to obtain the string description for example:
public static class EnumExtension
{
public static string ToDescription<TEnum>(this TEnum enumValue) where TEnum : struct
{
return ReflectionService.GetClassAttribute<DescriptionAttribute>(enumValue);
}
}
enum Type
{
[Description("One")]
value1 = 1
}
var value = Type.Value1;
Console.Writeline(value.ToDescription());
I'm always confused which kind of enumeration I should use. A hashtable, an enum, a struct a dictionary, an array (how oldschool), static strings...
Instead of using strings in my code I want to use a beautiful enum like so:
public enum MyConfigs
{
Configuration1,
Configuration2
}
Problem is that I don't always want to convert my enum toString() as I'm not interested in the index representation of the enum.
What is the best way to represent a public enumeration of string based values?
In the end I would love to end up with using MyConfigs.Configuration1 where needed in my code.
I prefer defining "grouped" constants as static members of a dummy static class, like so:
public static class FieldNames
{
public const string BRANCH_CODE = "_frsBranchCode";
public const string BATCH_ID = "_frsBatchId";
public const string OFFICE_TYPE = "_frsOfficeType";
}
But of course they are not "enumerable" directly, so you can't foreach over them unless you provide a static array too:
public static string[] AllFieldNames
{
get
{
return new string[]
{
FieldNames.BRANCH_CODE,
FieldNames.BATCH_ID,
FieldNames.OFFICE_TYPE
};
}
}
public static class MyConfigs
{
public const string Configuration1 = "foo",
Configuration2 = "bar"
}
This is then pretty-much identical to how enums are implemented (ignoring the whole "it must be an integer" thing).
Type-safe enum pattern?
public class StringEnum
{
#region Enum Values
public static readonly StringEnum ValueOne = new StringEnum("Value One");
public static readonly StringEnum ValueTwo = new StringEnum("Value Two");
#endregion
#region Enum Functionality
public readonly string Value;
private StringEnum(string value)
{
Value = value;
}
public override string ToString()
{
return value;
}
#endregion
}
You can use this like:
private void Foo(StringEnum enumVal)
{
return "String value: " + enumVal;
}
If you never need to pass these values around in a type-safe manner to methods etc. then it is probably best to just stick with a constants file.
I need advice on structures.
I have 2 sections of code. The first section is as below:
namespace Project.GlobalVariables
{
class IOCard
{
struct InputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
static InputCard[] InputCards = new InputCard[5];
public static string ACardNo = InputCards[1].CardNo;
public static string BCardNo = InputCards[2].CardNo;
}
}
The second portion is as below:
private void Form1_Load(object sender, EventArgs e)
{
IOCard.ACardNo = "Card A";
IOCard.BCardNo = "Card B";
MessageBox.Show(IOCard.ACardNo);
MessageBox.Show(IOCard.BCardNo);
}
My plan is to be able to assign and retrieve InputCards component by using IOCard as shown in Form1_Load.
However, when I compile the code, I get the following error.
Error 1 'Project.GlobalVariables.IOCard.InputCard.WriteBitNo': cannot have instance field initializers in structs E:\Programming\New platform\StandardPlatform\StandardPlatform\Project\GlobalVariables.cs 16 26 StandardPlatform
Can someone tell me how to solve the error?
Please advise. Thanks.
Here are the classes that I have attempted to create and use, but failed.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Project.GlobalVariables
{
static class IOCard
{
public const int TotalInputCard = 10;
public const int TotalOutputCard = 10;
public class InputCard
{
public string CardNo = "1";
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
public class OutputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo = new int[16];
public int[] ReadBitNo = new int[16];
}
public static InputCard[] InputCards = new InputCard[TotalInputCard];
public static OutputCard[] OutputCards = new OutputCard[TotalOutputCard];
public static int X100 = InputCards[0].WriteBitNo[0];
public static int Y100 = OutputCards[0].WriteBitNo[0];
}
}
I tried to use these in the Form_Load, like so:
private void Form1_Load(object sender, EventArgs e)
{
IOCard.X100 = 1;
IOCard.Y100 = 1;
}
No matter how much I have tried to search on the net for answers, I have got nowhere.
Please advise. Thanks.
In C#, a struct value is not a reference to an object in the way a value of a class type is. The value of a struct is the "union" of all the values of the instance fields of the struct.
Now, the default value of a struct type is the value where all those fields have their default values. Since the beginning of C#, the syntax:
new S() // S is a value-type
where S is a struct type, has been equivalent to the default value of that struct. There is no constructor call! This is the exact same value which can (nowadays) also be written
default(S) // S is a value-type
Now, things like
struct S
{
int field = 42; // non-static field with initializer, disallowed!
// ...
}
are illegal (cannot have instance field initializers in structs). They could give the impression that the field of a new S() would be 42, but in fact the field of new S() must be the default value of int (which is zero, distinct from 42).
With this explanation, you also see why it is not possible to create a non-static, zero-parameter constructor for a struct type, in C#.
What's it's trying to say is that when you have InputCards = new InputCard[5]; it will allocate a block of memory 5 times the size of an InputCard structure and set all of its bytes to 0. There is no opportunity to execute the int[] WriteBitNo = new int[16]; and such assignments, so you cannot have them.
Your options are to either manually call an initializer for your structs or make it a class and manually initialize the InputCards array with 5 new instances of InputCard.
You will neither be able to initialize a struct's fields nor define a default constructor to initialize it's fields. After looking at your struct, I recommend you use a class instead. It's not recommended to use a struct for a scenario where you have a bunch of fields.
Try this. Initialize the InputCard with a factory function Create():
namespace Project.GlobalVariables
{
class IOCard
{
struct InputCard
{
public string CardNo;
public int BaseAddress;
public int LowerAddress;
public int UpperAddress;
public int[] WriteBitNo;
public int[] ReadBitNo;
static InputCard Create()
{
return new InputCard()
{
CardNo = string.Empty,
WriteBitNo = new int[16],
ReadBitNo = new int[16]
};
}
}
static InputCard[] InputCards = new InputCard[]
{
InputCard.Create(),
InputCard.Create(),
InputCard.Create(),
InputCard.Create(),
InputCard.Create()
};
public static string ACardNo = InputCards[1].CardNo;
public static string BCardNo = InputCards[2].CardNo;
}
}
Use class instead of structure. Structure is used for small types like Point, which are faster to create on the stack and copy, than to create dynamically and pass by reference.
Not sure about the exception, but i have a solution.
You should not use "struct" for this class, it is too much (and storing too much data). If you define it as "class", the same code would work fine.
Is there a particular reason why you want this to be a struct rather than a class?
If you make it a class, it works just fine.