C# : Is there a way to pass an enum as an argument? - c#

I've searched (maybe not enough) but couldn't find an answer.
I want to make a generic function where I can pass any enum to use with a CheckedListBox (get or set the value).
public enum TypeFlags
{
None = 0x0,
//List of flag
}
private void makeFlagOrBitmask(CheckedListBox list, Type e)
{
int myFlags = 0x0;
//I want to achieve something like that
foreach (Object item in list.CheckedItems)
{
//(TypeFlags)Enum.Parse(typeof(TypeFlags), item);
//So e should be the enum himself, but i can't figure how to do that
myFlags += (int)((e)Enum.Parse(typeof(e), item.tostring()));
}
}
So, I can make/read any flags with a single function.
The problem is that I can't figure out how to pass the enum as I need it in the function.

might not be complete but it sounds like you need a generic Enum iterator. I picked up the below code from Create Generic method constraining T to an Enum
public T GetEnumFromString<T>(string value) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
//...
}

I know this is not a nice Code but this works for me:
If the method want an object instead of a type (maybe you can do this with a type) you can do it like this:
if (e.GetType() == typeof(ImageType))
{
ValueArray = GetEnumArray(ImageType.Bmg);
}
This way you can check what Enum it es before you do something.
I hope this can help you.

You want to change this line:
myFlags += (int)((e)Enum.Parse(typeof(e), item.tostring()));
Into this:
myFlags += (int)((e)Enum.Parse(e, item.tostring()));
Since e is already a type. As of how to pass the parameter:
makeFlagOrBitmask(myCheckBoxList, typeof(myEnum));
I hope this helps.
EDIT:
To make sure only enums will work, add this to the top of your function:
if (!e.IsEnum)
return;

Related

Generic method, how to get values if it is a List?

I have a generic method and it's possible that the object passed is a single object or a list of objects. Example:
public void MyGenericMethod<T>(T something, int? index)
{
// if it is a list how do I get to the object in the list?
}
There are cases when someone will pass a List. If they do pass a list of objects I will then use the index parameter to get the single object out of the list. I can assume that if index is not null then they passed in a list, but then how do I get to that value? I can't do this:
object temp = something[index.Value];
It's important to note that I cannot force the user to pass in a single object into my generic method. Also I cannot make it an array (T[]) and force the user to pass in an array (or a List).
You can use a cast to get the IList.
IList list = something as IList;
if( list != null )
{
object temp = list[index.Value];
}
However it might be simpler and more type safe to have a generic method overload dedicated to IList instead of one massive generic method.
public void MyGenericMethod<T>(IList<T> something, int index)
{
var item = something[index];
// etc...
}
Your requirements seem a bit wierd... why not do the following:
public void MyGenericMethod<T>(T something)
{
// let the user pass in the correct item
}
And simply let the user handle it, after all how is:
MyGenericMethod(MyList, 1);
Significantly better than:
MyGenericMethod(MyList[1])
???
Though if you really want I'd write it like so:
public void MyGenericMethod<T>(T something) //Base Method
{
// let the user pass in the correct item
}
public void MyGenericMethod<IList<T>>(IList<T> list, int index) //Overload
{
MyGenericMethod(list[index]);
}
Generics are meant to be used if your code does not care about the concrete type. If you still want to do this you need to cast:
IList list = (IList)something;
Or, if it is a generic list you need to do reflection access to invoke the list indexer at runtime if the element type is not statically known to you.
This (inefficient) snippet might also help you:
List<object> list = ((IEnumerable)something).Cast<object>().ToList();
Those are some ugly tricks. There is no clean way because, again, you are slightly misusing the feature.
Also, you don't need generics at all. Just type the parameter as object.
Like usr said, Generics aren't really supposed to be used in this way.
You could do a check to see if it's a list and if so iterate over it like this:
IList<T> enumerable = something as IList<T>;
if (enumerable != null)
{
foreach (T item in enumerable)
{
// Do something
}
}
If your T can be anything (which I don't recommend, since it breaks the SOLID principle) and what to handle it as a list you can do:
public void MyGenericMethod<T>(T something, int? index)
{
IList list = something as IList;
if (list != null)
{
//Do Something
}
else
{
//Do something else
}
}
Or you can do one of the following:
public void MyGenericMethod<T>(T something, int? index) where T : IList
{
IList list = (IList)something; //This will always work ok
//Do Something
}
I recommend the following, if feasible
public void MyGenericMethod(IList something, int? index)
{
//Do Something
}

Determine type of Enum

I have two Enumerators and a method that takes an enumerator. They are called ABC and DEF and the method is called TestMethod(Enum myEnum). Code is below:
public enum ABC
{
Zero,
One,
Two
};
public enum DEF
{
Zero,
One,
Two
};
public void TestEnum(Enum myEnum)
{
...
}
The function TestEnum takes any enumerator. How can I test which one of the two does the passed in parameter belong to? I could blindly start testing it out with try / catch casting but sheesh that's ugly. Any cleaner ways of doing this? Thank you in advance for any help.
How can I test which one of the two does the passed in parameter belong to?
You can just call GetType:
Type type = myEnum.GetType();
It's not clear what you want to do with it after that, mind you.
Alternatively:
if (myEnum is ABC)
{
}
else if (myEnum is DEF)
{
}
EDIT: If you're able to change the method signature and if your callers will know the type, then as per Jeppe's comment, you could use:
public void TestEnum<T>(T value) where T : struct
{
// Use typeof(T) here
}
You can't constrain T to be an enum type with normal C#... although there are hacky ways of writing code with such constraints applied via post-processing.
Mr. Skeet already nailed this but!
What about two methods.
public void TestEnum(ABC abcEnum) {
//do ABC stuff
}
public void TestEnum(DEF defEnum) {
//do DEF stuff
}
You get the branching you need but without having to worry about getting the if statement right. True it's only an if statement but what if you add enum GHI. Now there's some unaccounted for input for TestEnum to handle. Using overloaded methods you'd catch that while compiling (or even better, intellisense would catch you).

Expression Tree that can represent an object OR a list of that object?

public returnType ReturnProperty<T>(Expression<Func<T, returnType>> property) where T : MyObject
{
// Some code or something
}
Obviously this is not my actual function, but basically what I want is to be able to select either an object of MyObject or an object of List<MyObject>. What should I replace returnType with for this to be possible? Is it possible at all? Do I have alternatives besides making returnType be object?
Note: Also, I did not know what tags to put on this question, sorry.
Edit: Also, the reason I need to be able to do both is I wanted to have an array of them or something. Like Expression<Func<T, returnType>>[] properties. Maybe this gives me more or less options.
You can have the function return object. object is anything, so it could be MyObject or List<MyObject>. You can then do things like this:
object retval = ReturnProperty(...)
if (retval is MyObject)
{
}
else if (retval is IEnumerable<MyObject>) // Works for List, array, etc.
{
}
The short answer is that if you can't write it as direct c# code, you can't write it as an expression tree.
Not that I think it's at all a good idea, but you could define a collection which has an implicit conversion from the contained type, which would allow you to use an expression which only takes a collection as a parameter, e.g.:
private static void ProcessItems(ItemCollection c) {}
ProcessItems(new Item());
// ...
class Item {}
class ItemCollection : List<Item>
{
public static implicit operator ItemCollection(Item item)
{
return new ItemCollection {item};
}
}

How to learn whether an interface is derived from a specific interface?

I have an interface like that:
public interface IViewA : IViewB, IViewC
{
byte prop { get; set; }
}
and I have a generic method like that:
public void OpenPopup<T>(WindowState state)
{
if ((typeof(T) as IViewC)!=null)
{
//Process A
}
else
{
//Process B
}
}
Although I send T as an interface which derives from IViewC, Process A is not being processed.
So how to learn at runtime via reflection whether an interface derives from other interface?
thanks
Try the following
if ( typeof(IViewC).IsAssignableFrom(typeof(T)) {
...
}
Instead of typeof use isAssignableFrom.
Try something like typeof(IViewC).IsAssignableFrom(typeof(T)).
Right now you're trying to treat typeof(T), which is a System.Type as IViewC, which will not work.
typeof(T) as IViewC is completely wrong. You are trying to cast from Type to IViewC, which will always fail, always resulting in null.
You want typeof(T).GetInterfaces(), and look through the returned list to see if your interface is in there.
if ((typeof(T) as IViewC)!=null)
This is wrong. What you wrote tests whether the Type object returned by typeof(T) is an IViewC, which it obviously isn't.
You want:
if (typeof(IViewC).IsAssignableFrom(typeof(T))

Generics in c# & accessing the static members of T

My question concerns c# and how to access Static members ... Well I don't really know how to explain it (which kind of is bad for a question isn't it?) I will just give you some sample code:
Class test<T>{
int method1(Obj Parameter1){
//in here I want to do something which I would explain as
T.TryParse(Parameter1);
//my problem is that it does not work ... I get an error.
//just to explain: if I declare test<int> (with type Integer)
//I want my sample code to call int.TryParse(). If it were String
//it should have been String.TryParse()
}
}
So thank you guys for your answers (By the way the question is: how would I solve this problem without getting an error). This probably quite an easy question for you!
Edit: Thank you all for your answers!
Though I think the try - catch phrase is the most elegant, I know from my experience with vb that it can really be a bummer. I used it once and it took about 30 minutes to run a program, which later on only took 2 minutes to compute just because I avoided try - catch.
This is why I chose the switch statement as the best answer. It makes the code more complicated but on the other hand I imagine it to be relatively fast and relatively easy to read. (Though I still think there should be a more elegant way ... maybe in the next language I learn)
Though if you have some other suggestion I am still waiting (and willing to participate)
The problem is that TryParse isn't defined on an interface or base class anywhere, so you can't make an assumption that the type passed into your class will have that function. Unless you can contrain T in some way, you'll run into this a lot.
Constraints on Type Parameters
Short answer, you can't.
Long answer, you can cheat:
public class Example
{
internal static class Support
{
private delegate bool GenericParser<T>(string s, out T o);
private static Dictionary<Type, object> parsers =
MakeStandardParsers();
private static Dictionary<Type, object> MakeStandardParsers()
{
Dictionary<Type, object> d = new Dictionary<Type, object>();
// You need to add an entry for every type you want to cope with.
d[typeof(int)] = new GenericParser<int>(int.TryParse);
d[typeof(long)] = new GenericParser<long>(long.TryParse);
d[typeof(float)] = new GenericParser<float>(float.TryParse);
return d;
}
public static bool TryParse<T>(string s, out T result)
{
return ((GenericParser<T>)parsers[typeof(T)])(s, out result);
}
}
public class Test<T>
{
public static T method1(string s)
{
T value;
bool success = Support.TryParse(s, out value);
return value;
}
}
public static void Main()
{
Console.WriteLine(Test<int>.method1("23"));
Console.WriteLine(Test<float>.method1("23.4"));
Console.WriteLine(Test<long>.method1("99999999999999"));
Console.ReadLine();
}
}
I made a static dictionary holding a delegate for the TryParse method of every type I might want to use. I then wrote a generic method to look up the dictionary and pass on the call to the appropriate delegate. Since every delegate has a different type, I just store them as object references and cast them back to the appropriate generic type when I retrieve them. Note that for the sake of a simple example I have omitted error checking, such as to check whether we have an entry in the dictionary for the given type.
To access a member of a specific class or interface you need to use the Where keyword and specify the interface or base class that has the method.
In the above instance TryParse does not come from an interface or base class, so what you are trying to do above is not possible. Best just use Convert.ChangeType and a try/catch statement.
class test<T>
{
T Method(object P)
{
try {
return (T)Convert.ChangeType(P, typeof(T));
} catch(Exception e) {
return null;
}
}
}
One more way to do it, this time some reflection in the mix:
static class Parser
{
public static bool TryParse<TType>( string str, out TType x )
{
// Get the type on that TryParse shall be called
Type objType = typeof( TType );
// Enumerate the methods of TType
foreach( MethodInfo mi in objType.GetMethods() )
{
if( mi.Name == "TryParse" )
{
// We found a TryParse method, check for the 2-parameter-signature
ParameterInfo[] pi = mi.GetParameters();
if( pi.Length == 2 ) // Find TryParse( String, TType )
{
// Build a parameter list for the call
object[] paramList = new object[2] { str, default( TType ) };
// Invoke the static method
object ret = objType.InvokeMember( "TryParse", BindingFlags.InvokeMethod, null, null, paramList );
// Get the output value from the parameter list
x = (TType)paramList[1];
return (bool)ret;
}
}
}
// Maybe we should throw an exception here, because we were unable to find the TryParse
// method; this is not just a unable-to-parse error.
x = default( TType );
return false;
}
}
The next step would be trying to implement
public static TRet CallStaticMethod<TRet>( object obj, string methodName, params object[] args );
With full parameter type matching etc.
This isn't really a solution, but in certain scenarios it could be a good alternative: We can pass an additional delegate to the generic method.
To clarify what I mean, let's use an example. Let's say we have some generic factory method, that should create an instance of T, and we want it to then call another method, for notification or additional initialization.
Consider the following simple class:
public class Example
{
// ...
public static void PostInitCallback(Example example)
{
// Do something with the object...
}
}
And the following static method:
public static T CreateAndInit<T>() where T : new()
{
var t = new T();
// Some initialization code...
return t;
}
So right now we would have to do:
var example = CreateAndInit<Example>();
Example.PostInitCallback(example);
However, we could change our method to take an additional delegate:
public delegate void PostInitCallback<T>(T t);
public static T CreateAndInit<T>(PostInitCallback<T> callback) where T : new()
{
var t = new T();
// Some initialization code...
callback(t);
return t;
}
And now we can change the call to:
var example = CreateAndInit<Example>(Example.PostInitCallback);
Obviously this is only useful in very specific scenarios. But this is the cleanest solution in the sense that we get compile time safety, there is no "hacking" involved, and the code is dead simple.
Do you mean to do something like this:
Class test<T>
{
T method1(object Parameter1){
if( Parameter1 is T )
{
T value = (T) Parameter1;
//do something with value
return value;
}
else
{
//Parameter1 is not a T
return default(T); //or throw exception
}
}
}
Unfortunately you can't check for the TryParse pattern as it is static - which unfortunately means that it isn't particularly well suited to generics.
The only way to do exactly what you're looking for would be to use reflection to check if the method exists for T.
Another option is to ensure that the object you send in is a convertible object by restraining the type to IConvertible (all primitive types implement IConvertible). This would allow you to convert your parameter to the given type very flexibly.
Class test<T>
{
int method1(IConvertible Parameter1){
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
}
}
You could also do a variation on this by using an 'object' type instead like you had originally.
Class test<T>
{
int method1(object Parameter1){
if(Parameter1 is IConvertible) {
IFormatProvider provider = System.Globalization.CultureInfo.CurrentCulture.GetFormat(typeof(T));
T temp = Parameter1.ToType(typeof(T), provider);
} else {
// Do something else
}
}
}
Ok guys: Thanks for all the fish. Now with your answers and my research (especially the article on limiting generic types to primitives) I will present you my solution.
Class a<T>{
private void checkWetherTypeIsOK()
{
if (T is int || T is float //|| ... any other types you want to be allowed){
return true;
}
else {
throw new exception();
}
}
public static a(){
ccheckWetherTypeIsOK();
}
}
You probably cant do it.
First of all if it should be possible you would need a tighter bound on T so the typechecker could be sure that all possible substitutions for T actually had a static method called TryParse.
You may want to read my previous post on limiting generic types to primitives. This may give you some pointers in limiting the type that can be passed to the generic (since TypeParse is obviously only available to a set number of primitives ( string.TryParse obviously being the exception, which doesn't make sense).
Once you have more of a handle on the type, you can then work on trying to parse it. You may need a bit of an ugly switch in there (to call the correct TryParse ) but I think you can achieve the desired functionality.
If you need me to explain any of the above further, then please ask :)
Best code: restrict T to ValueType this way:
class test1<T> where T: struct
A "struct" here means a value type.
String is a class, not a value type.
int, float, Enums are all value types.
btw the compiler does not accept to call static methods or access static members on 'type parameters' like in the following example which will not compile :(
class MyStatic { public static int MyValue=0; }
class Test<T> where T: MyStatic
{
public void TheTest() { T.MyValue++; }
}
=> Error 1 'T' is a 'type parameter', which is not valid in the given context
SL.
That is not how statics work. You have to think of statics as sort of in a Global class even if they are are spread across a whole bunch of types. My recommendation is to make it a property inside the T instance that can access the necessary static method.
Also T is an actual instance of something, and just like any other instance you are not able to access the statics for that type, through the instantiated value. Here is an example of what to do:
class a {
static StaticMethod1 ()
virtual Method1 ()
}
class b : a {
override Method1 () return StaticMethod1()
}
class c : a {
override Method1 () return "XYZ"
}
class generic<T>
where T : a {
void DoSomething () T.Method1()
}

Categories