I want to define a function with a parameter, that paramter must be a specific, defined in a list (for example)
i remember doing this years ago but my memory has failed me.
example
public void foo(specific choice list defined in my class){}
specific-list = x,y,z
consume it list this (i think)
foo(myclass.x)
To expand on #kaffekopp's comment, it seems likely that you are talking about an enum, i.e.
public enum MyEnum // declare the enum type (optional: specify an underlying integer type)
{
Apple, // define the choices (note: enums are **not** strictly enforced;
Pear, // they are just named integers, and at runtime you can be surprised to find
Bicycle, // that the actual value is 42, a value you never defined)
}
with (on MyClass):
public MyEnum SomeProp {get;set;} // define a property as being of that enum type
and:
public void Foo(MyEnum option) {...} // define a method that takes a parameter of the type
then either:
Foo(MyEnum.Bicycle); // passing a constant/literal
or:
MyClass obj = ...
Foo(obj.SomeProp); // passing an existing value from somewhere
Related
Intention :
I am writing a business application that uses multiple enums where most of these enums exists in tables in the database too. The problem comes in maintenance when one of the team members or a late developer changes an enum member value at one of the two places leaving the enum unsynced. To solve this problem I am trying to create a custom enum attribute that throws some exception when it finds that an enum values are not in sync.
Implementation :
[AttributeUsage(AttributeTargets.Enum)]
public class EnumSyncAtrribute : Attribute
{
public EnumSyncAtrribute(Type databaseAccessType, Type enumType))
{
// Code that uses that databaseAccessType to access the database to get
// enum values then compare it to values of enumType , goes here.
}
}
Then target enum is marked as follows
[EnumSyncAtrribute(typeof(MyDataBaseAccess), typeof(MyEnum))]
public enum MyEnum
{
value1 = 0,
value2 = 1,
value3 = 2
}
Problem :
The problem is this attribute constructor never executes! I have tried replacing Enums with Classes and found that it executes fine, but with Enums, no!
The question is, when custom attributes are used for enums, when does their constructors executes?
The attribute is constructed only when you retrieve it (using the GetCustomAttribute function). Otherwise, its construction recipe (constructor overload + positional parameters + properties values) is only stored in the assembly metadata.
In your case, I'd retieve all enum types from the assembly, and check if they have the attribute. Something like that at the startup of your application:
var allEnumTypes = Assembly.GetExecutingAssembly()
.GetTypes()
.Where(t => t.IsEnum);
foreach(var enumType in allEnumTypes)
{
var syncAttr = Attribute.GetCustomAttribute(enumType, typeof(EnumSyncAtrribute)) as EnumSyncAtrribute;
if (syncAttr != null)
{
// Possibly do something here, but the constructor was already executed at this point.
}
}
I have this extension method for an Enum:
public static List<Enum> Values(this Enum theEnum)
{
return Enum.GetValues(theEnum.GetType()).Cast<Enum>().ToList();
}
I'm getting a code analysis violation:
CA1062 Validate arguments of public methods
In externally visible
method 'EnumExtensions.Values(this Enum)', validate parameter
'theEnum' before using it.
Why is that happening? How can I validate the parameter? I can't check for null because an enum is a non-nullable value type. Is there some other check that is supposed to be occurring here?
I can't check for null because an enum is a non-nullable value type.
Any particular enum is a value type, but Enum itself isn't. (Just like ValueType isn't a value type either... every type derived from ValueType except Enum is a value type.)
In other words, I could write:
Enum foo = null;
var bang = foo.GetValues();
That would compile and then fail at execution time with a NullReferenceException.
Given that you ignore the value except to get its type, I'd actually suggest removing it and either accepting a Type or making it generic in the type of enum you want. But if you want to keep the current signature, you just need:
if (theEnum == null)
{
throw new ArgumentNullException();
}
You might also want to look at my Unconstrained Melody project which provides a bunch of helper methods for enums, generically constrained to enum types via IL manipulation.
The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list.
It is used just for declare another enums. In any case, the input should be your declaration.
public enum theEnum {
enum1,
enum2
}
public void ShowEnum(theEnum e)
{
System.Console.WriteLine(e.GetType());
}
How can I call a method that expects an int value by using an enum member. I dont want the called method to have to know about the enum.
public enum Volume : int
{
Low = 1,
Medium = 2,
High = 3
}
public void Start() {
DoSomeWork(Volume.Low); //this complains
//this works DoSomething((int)Volume.Low);
}
public void DoSomeWork(int vol) {
//Do something
}
Cast it explicitly to int (as you have already figured out):
DoSomeWork((int)Volume.Low)
Implicit conversion from enum to underlying type is forbidden, since there are a lot of cases when this conversion does not make sense. #EricLippert explains this well enough here.
However why introduce the enum if you are not using it? If the volume rate in your program is specified by the enum - then this is the type your method should expect as a parameter.
Call it like this:
DoSomeWork( (int) Volume.Low );
Why not using this way:
public void DoSomeWork(Volume volume) {
//Do something
}
as documentation states
Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of the enumeration elements is int.
so you can just simple cast it to int and pass it to the method that way.
DoSomeWork((int)Volume.Low);
I have many Enum types which return from a service and which I want to map to my Enum types.
What I want is to create a mapper class which has all the conversion logic.
I did something like this:
public static class ErrEnumMapper
{
private static Dictionary<FullErrorTypeError, eError> dictionary;
static ErrEnumMapper()
{
var dictionary = new Dictionary<FullErrorTypeError, eError>()
{
{FullErrorTypeError.APP, eError.APPLICATION},
{FullErrorTypeError.INF, eError.INF},
{FullErrorTypeError.NO, eError.NONE},
{FullErrorTypeError.PAX, eError.PASSENGER},
{FullErrorTypeError.SYS, eError.SYSTEM}
};
}
public static eError GetEnum(FullErrorTypeError key)
{
var val = dictionary[key];
if (val != null)
return val;
throw new InvalidOperationException();
}
}
But since I have many other Enums, in this way, I will have to create many static fields (like the "dictionary" fields) and their equivalent method (Like "GetEnum")...is there a better way to do this?
Generic maybe?
Unless the integral values or names are the same for both sets of enums are the same, you can't transpose from one enum value to another without some sort of manual mapping.
Some suggestions:
Reuse the original enums if possible
Keep the integer values of the mapped enum the same as the original enum, so you can just cast from one to another.
Use a convention for the enum names so you can map from one to the other.
Use a custom attribute on each mapped enum value that indicates the correlating original enum value, and have ErrEnumMapper read that attribute. Still manual mapping, just perhaps reorganized.
Of course, in the spirit of KISS, I'd stick with #1, #2, or just deal with the manual mapping.
Maybe I'm not really getting what you mean.. but you can just explicitly cast them if they have the same underlying value:
enum FirstEnum {
ONE,
TWO,
THREE
}
enum SecondEnum {
FOUR,
FIVE,
SIX
}
static void Main(string[] args) {
FirstEnum first = FirstEnum.ONE;
SecondEnum second = (SecondEnum)first;
Console.WriteLine(second); // prints FOUR
}
This allows you to keep your naming convention..
I am designing a custom attribute class.
public class MyAttr: Attribute
{
public ValueRange ValRange { get; set; }
}
Then I am attempting to assign this attribute to a property in an adjoining class:
public class Foo
{
[MyAttr(ValRange= new ValueRange())]
public string Prop { get; set; }
}
However, the compiler is complaining the following:
'ValRange' is not a valid named attribute argument because it is not a valid attribute parameter type
I also tried converting the ValueRange class to a struct in hopes that become a value type might solve the problem. Is there any way around this?
Is there any way around this?
No.
For more details I refer you to section 17.1.3 of the C# 4 specification, which I reproduce here for your convenience:
The types of positional and named parameters for an attribute class are limited to the attribute parameter types, which are:
One of the following types: bool, byte, char, double, float, int, long, sbyte, short, string, uint, ulong, ushort.
The type object.
The type System.Type.
An enum type, provided it has public accessibility and the types in which it is nested (if any) also have public accessibility.
Single-dimensional arrays of the above types.
A constructor argument or public field which does not have one of these types, cannot be used as a positional or named parameter in an attribute specification.
Remember, the point of an attribute is to at compile time add information to the metadata associated with the entity upon which you've placed the attribute. That means that all the information associated with that attribute must have a well-defined, unambiguous way to serialize it into and out of metadata. By restricting the set of legal types to a small subset of all possible types we ensure that the compiler can always emit legal metadata that the consumer can understand.
Attribute parameter values need to be resolvable at compile time (i.e constants).
See Attribute Parameter Types on MSDN:
Values passed to attributes must be known to the compiler at compile time.
If you can create a ValueRange that is a constant, you can use it.
Is there any way around this?
Yes.
You can have your attribute use a Type property and then use types that implement a defined interface, for which the code that processes that attribute would have to assume, and as such also create an implicit, but hopefully documented, requirement to its clients:
public interface IValueRange {
int Start { get; }
int End { get; }
}
public class MyAttr : Attribute {
// The used type must implement IValueRange
public Type ValueRangeType { get; set; }
}
// ....
public class Foo {
class FooValueRange : IValueRange {
public int Start { get { return 10; } }
public int End { get { return 20; } }
}
[MyAttr(ValueRangeType = typeof(FooValueRange))]
public string Prop { get; set; }
}
This is not unlike many classes in the System.ComponentModel namespace, like DesignerAttribute.
Attribute parameters must be values of the following types (quoting the article):
Simple types (bool, byte, char, short, int, long, float, and double)
string
System.Type
enums
object (The argument to an attribute parameter of type object must be a constant value of one of the above types.)
One-dimensional arrays of any of the above types
Edit: Changed "compile-time constant" to "value", since types and arrays are not constants (thanks to the commenter who pointed this out (and subsequently deleted his comment for some reason...))
Attributes can only receive compile-time-constants as parameters (e.g. 3, "hello", typeof(MyClass), "path to a resource defining whatever non constant data you need").
The last example (passing a type) I gave may help you design a workaround (pass a type implementing an interface with the method you need).