I've got a static class with static getters.
public static class Cars
{
public static KeyValuePair<Guid, string> Acura
{
get { return new KeyValuePair<Guid, string>(new Guid("MMMMMMMM-509B-477A-ADB1-5CD014B41001"), "Acura"); }
}
public static KeyValuePair<Guid, string> AlfaRomeo
{
get { return new KeyValuePair<Guid, string>(new Guid("MMMMMMMM-509B-477A-ADB1-5CD014B41002"), "Alfa Romeo"); }
}
// etc.
}
I need to retrieve all the static properties from this static class and do something with each KeyValuePair. But the following throws a System.FormatException at runtime saying that it could not find recognizable digits
Type type = typeof(Cars);
foreach(var manufacturer in type.GetProperties())
{
if(manufacturer.PropertyType == typeof(KeyValuePair<Guid, string>))
{
var v = manufacturer.GetValue(null, null); //this does not work
// How to get the KeyValuePair<Guid, string>?
}
}
How to get each KeyValuePair?
UPDATE: Sorry.. the solution works perfectly, the problem is that GUID are not valuid Guids.. M is not hexadecimal character
This does not have to do anything with reflection or static properties. Within the getters of your properties there are exceptions thrown.
"MMMMMMMM-509B-477A-ADB1-5CD014B41001" and "MMMMMMMM-509B-477A-ADB1-5CD014B41002" are no valid Guids. Create Guids with valid values and the properties won't throw the exceptions.
Each of the digits in a Guid must be a hexadecimal digit (see here).
new Guid("MMMMMMMM-509B-477A-ADB1-5CD014B41001")
will throw the exception, while for example
new Guid("00000000-509B-477A-ADB1-5CD014B41001")
won't.
Related
Attempting to retrieve the Value of an EntryStatus(class further down), ie ("READY", "DELETED", "ERROR_IMPORTING") in a manner similar to the immediately below
EntryStatus test = EntryStatus.DELETED;
Console.WriteLine(test);
EntryStatus value = test;
string val = value.ToString();//see note1
Console.WriteLine(val);
The result of the above code is:
3
3
I would like to have the second Console.WriteLine to return "DELETED"
I do not understand how to retrieve the alphabetic part of the enum.
note1: changing this line to
int val = (int)value;
gives an error of Cannot Convert EntryStatus to int. This enum seems not to behave like other C# enums.
The EntryStatus is child class of StringEnum.
Edit: EntryStatus is part of the Kaltura Generated API and should not be modified.
public sealed class EntryStatus : StringEnum
{
public static readonly EntryStatus ERROR_IMPORTING = new EntryStatus("-2");
public static readonly EntryStatus ERROR_CONVERTING = new EntryStatus("-1");
public static readonly EntryStatus IMPORT = new EntryStatus("0");
public static readonly EntryStatus INFECTED = new EntryStatus("virusScan.Infected");
public static readonly EntryStatus SCAN_FAILURE = new EntryStatus("virusScan.ScanFailure");
public static readonly EntryStatus PRECONVERT = new EntryStatus("1");
public static readonly EntryStatus READY = new EntryStatus("2");
public static readonly EntryStatus DELETED = new EntryStatus("3");
public static readonly EntryStatus PENDING = new EntryStatus("4");
public static readonly EntryStatus MODERATE = new EntryStatus("5");
public static readonly EntryStatus BLOCKED = new EntryStatus("6");
public static readonly EntryStatus NO_CONTENT = new EntryStatus("7");
private EntryStatus(string name) : base(name) { }
}
The base class StringEnum is:
Edit: The StringEnum class is part of the Kaltura Generated API, should not change
public class StringEnum
{
private readonly string name;
protected StringEnum(string name)
{
this.name = name;
}
public override string ToString()
{
return name;
}
public static StringEnum Parse(Type type, string name)
{
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo field in fields)
{
object val = field.GetValue(null);
if (val.GetType().BaseType == typeof(StringEnum))
{
if (val.ToString() == name)
return (StringEnum)val;
}
}
return null;
}
}
}
Please accept System.Reflection, EntryStatus class and StringEnum class as givens for the problem. Modifications to EntryStatus and StringEnum can be done with the keyword partial only. I am attempting to understand the Kaltura Generated API library these are part of. All of your help is greatly appreciated.
-- Update --
This is an update after the re-write of your question.
I'm not quite sure what to call what to call what you are looking for. Right now, I used "OtherName".
This solution assumes two things.
The Kaltura Generated API (that should not be modified) exists as source in your project
Names associated with your EntryStatus things are unique (or mostly unique).
Possible Solution:
Create a new file in your project named EntryStatus.partial.cs. Add the following code:
public sealed partial class EntryStatus
{
private Dictionary<string, string> _namesDictionary = null;
public string AsOtherName()
{
if (_namesDictionary == null)
{
var fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
_namesDictionary = new Dictionary<string, string>(fields.Length);
foreach (var field in fields)
{
var fieldValue = field.GetValue(null);
var fieldName = (fieldValue as EntryStatus).ToString();
_namesDictionary[fieldName] = field.Name;
}
}
return _namesDictionary[ToString()];
}
}
That acts to modify the EntryStatus definition, but without touching the existing code. If that's too intimate a relationship, you'd need to build a class that reflects over the EntryStatus class and builds that dictionary.
When it's all finished, EntryStatus.ERROR_CONVERTING.AsOtherName() returns "ERROR_CONVERTING".
Then again, what's the point of typing EntryStatus.ERROR_CONVERTING and having a whole lot of code only to come up with "ERROR_CONVERTING"
--- Old Answer ---
I'm not quite sure what you are trying to do, but this might help:
First, I changed your Parse function to be generic, and to include a TryParse method as well (trust me, you'll appreciate it). Your current Parse returns null on failure. The expectation of most users is that an exception is thrown will be thrown from a Parse method on failure.
The code below does what I think you are describing, but I'm pretty sure that it doesn't do what you want. See my suggested changes below for what I think you want.
The biggest change is that I changed your FieldInfo[] fields = type.GetFields(); to var fields = type.GetFields(BindingFlags.Public|BindingFlags.Static); Your EntryStatus class only has static members, and it's not instantiable by anyone outside itself (so it doesn't really matter).
The new Parse (and TryParse) code:
public static bool TryParse<T>(string name, out StringEnum stringEnum) where T : StringEnum
{
stringEnum = null;
var type = typeof(T);
var fields = type.GetFields(BindingFlags.Public|BindingFlags.Static);
foreach (var field in fields)
{
var val = field.GetValue(null);
if (val is StringEnum typedVal)
{
if (typedVal.ToString() == name)
{
stringEnum = typedVal;
return true;
}
}
}
return false;
}
and
public static StringEnum Parse<T>(string name) where T: StringEnum
{
if (StringEnum.TryParse<T>(name, out var val))
{
return val;
}
else
{
return null; //you should probably make this throw
}
}
With that, if I say this:
Debug.WriteLine(StringEnum.Parse<EntryStatus>("virusScan.Infected"));
I get
virusScan.Infected
So...
What I think you want instead is to change:
if (typedVal.ToString() == name) //in my TryParse method
to
if (field.Name == name)
Now, if you run StringEnum.Parse<EntryStatus>("SCAN_FAILURE") you will get:
virusScan.ScanFailure
Is that close to what you are talking about? If you want a better answer, you will need to remove most of what starts with the paragraph that starts with "I call the API" and replace it with text and code that makes up a Minimal Reproduceable Example. For example the code block immediately after the "I call the API" paragraph does not include StringEnum or EntryStatus. I really can't tell what you are talking about.
As a final note, you may want to include an implicit operator on your StringEnum class that allows implicit conversions to string. If you don't want implicit conversions, you should at least provide an explicit operator to allow casting to strings. See: User-defined Implicit and Explicit Conversion Operators
I suppose you want to model the KalturaEntryStatus and other similar enums. In my opinion is reflection a bit overkill here. So I propose another solution, which is based on a simple Dictionary<string, string> as also suggested by #Flydog57.
The sample contains only two enums with only 2 members:
/// <summary>
/// Contains the various return codes of Kaltura API functions.
/// </summary>
public class KalturaEnum
{
/// <summary>
/// Contains the return codes for function XXX.
/// </summary>
public static readonly KalturaEnum KalturaEntryStatus = new KalturaEnum(nameof(KalturaEntryStatus),
("-2", "Error importing"),
("-1", "Error converting")
);
/// <summary>
/// Contains the return codes for function YYY.
/// </summary>
public static readonly KalturaEnum KalturaBatchJobType = new KalturaEnum(nameof(KalturaBatchJobType),
("ReachInternal.ReachInternalQueueHandler", "Reach internal queue handler"),
("0", "Convert")
);
private readonly Dictionary<string, string> values;
private KalturaEnum(string enumName, params (string Code, string Description)[] values)
{
if (string.IsNullOrWhiteSpace(enumName))
throw new ArgumentException($"'{nameof(enumName)}' cannot be null or whitespace.", nameof(enumName));
EnumName = enumName;
this.values = values.ToDictionary(a => a.Code, a => a.Description, StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Gets the name of this enumeration (not really usefull...).
/// </summary>
public string EnumName { get; }
/// <summary>
/// Gets the description of a return code by using a case-insensitive search.
/// </summary>
/// <param name="code">The return code of a API function.</param>
/// <returns>The description for <paramref name="code"/> or "Unknown return value '<paramref name="code"/>' for the type <see cref="EnumName"/>."</returns>
public string GetDescription(string code) => code != null && values.TryGetValue(code, out var name) ? name : $"Unknown return value '{code ?? "null"}' for the type {EnumName}.";
}
Test and output:
Console.WriteLine(KalturaEnum.KalturaEntryStatus.GetDescription("-2"));
Console.WriteLine(KalturaEnum.KalturaBatchJobType.GetDescription("1"));
Error importing
Unknown return value '1' for the type KalturaBatchJobType.
In your code it would look like this:
foreach (MediaEntry MediaEntry in result.Objects)
{
Console.WriteLine(KalturaEnum.KalturaEntryStatus.GetDescription(MediaEntry.Status));
}
This seems like the most basic thing ever but somehow I couldnt find the answer and couldnt figure it out.
Lets say I have a custom class:
public class WineCellar
{
public string year;
public string wine;
public double nrbottles;
}
Now I would like a function:
WineCellar ex = new WineCellar();
ex.members();
This should return: year, wine, nrbootles.
And:
ex.members().types();
Should return: string, string, double
I guess on the same note, lets say you have one instance {2010, Rioja, 6}. Is there syntax that returns these by indexing? i.e.
ex[1]
or
ex.{1}
that returns 2010?
Sorry for the basic question.
As Michelle said in the comments, this sounds like a wrong approach to a bigger problem.
However, if you do need this kind of things, you can get the using reflection:
//returns a list of propertyInfo objects for the class
// with all kinds of usefull information
public List<PropertyInfo> GetMemberInfos()
{
return this.GetType().GetProperties().ToList();
}
//returns a list of property names
public List<string> GetMemberNames
{
return this.GetType().GetProperties().Select(pi => pi.Name).ToList();
}
//returns a list of names of the property types
public List<string> GetMemberTypeNames
{
return this.GetType().GetProperties().Select(pi => pi.PropertyType.Name).ToList();
}
//indexer that uses the property name to get the value
//since you are mixing types, you can't get more specific than object
public object this[string property]
{
get { return this.GetType().GetProperty(property).GetValue(this); }
set { this.GetType().GetProperty(property).SetValue(this, value); }
}
//indexer that uses the property index in the properties array to get the value
public object this[int index]
{
get { return this.GetType().GetProperties()[index].GetValue(this); }
set { this.GetType().GetProperties()[index].SetValue(this, value); }
}
Note that all of these methods are very slow, because in general, reflection is slow. You can try to cache some thing to speed it up.
Also, the last method is downright dangerous. It will (try to) read and write to an array that does not have a guaranteed order. In fact, the documentation specifies:
The GetProperties method does not return properties in a particular
order, such as alphabetical or declaration order. Your code must not
depend on the order in which properties are returned, because that
order varies.
For example, if you change your class to:
public class WineCellar
{
public string year;
public string region;
public string wine;
public double nrbottles;
}
and you were used to using winecellar[1] = "Pinot Noir" that will most likely now update the region property, instead of the wine property.
This is how you would implement Members method (In case if you wanted property names as strings)
public List<string> Members()
{
List<string> propNames = new List<string>();
foreach (var prop in typeof(WineCellar).GetProperties())
{
propNames.Add(prop.Name);
}
return propNames;
}
And this is how you would implement Types (In same case)
public List<string> Types()
{
List<string> propTypes = new List<string>();
foreach (var prop in typeof(WineCellar).GetProperties())
{
propTypes.Add(prop.PropertyType.ToString());
}
return propTypes ;
}
And the last thing if you want to get values of the parameters like this ex[n] you can just make a simple indexer in you class like this
public string this[int n]
{
get
{
int current = 0;
foreach (var prop in typeof(WineCellar).GetProperties())
{
if (current == n)
return prop.GetValue(this, null).ToString();
current++;
}
return null;
}
}
but for these methods to work you should change your variables into properties like this
public class WineCellar
{
public string Year { get; set; }
public string Wine { get; set; }
public double Nrbottles { get; set; }
}
You can use reflection
foreach (var prop in typeof(WineCellar).GetProperties())
{
if (prop.PropertyType == typeof(double) || prop.PropertyType == typeof(double?))
{
}
}
to get the value, you can do:
prop.GetValue(obj);
There is a very easy trick which creates a dictionary-like structure where keys are types.
The structure acts like a Dictionary<Type, T?> where keys are Type objects and values are instances of the corresponding types.
This wonderful structure is as fast as just a variable or array since the "lookup" is only done once by the compiler/JITter and the proper value reference is compiled into your program.
public static class MyDict<T> {
public static T Value { get; set; }
}
You can work with that structure like this:
MyDict<string>.Value = MyDict<int>.Value.ToString();
The problem is that this "dictionary" is global. The only way to create different dictionaries is to create different classes.
How can create a similar (fastest "lookup", no boxing) non-static structure? (Without code generation.)
Simply said: I want to have multiple Dictionary<Type, object>-like objects without lookup costs, casting and boxing.
Here's an approach that extends the method described in the question:
public class TypeDict
{
public T Get<T>()
{
return MyDict<T>.Values[this];
}
public void Set<T>(T value)
{
MyDict<T>.Values[this] = value;
}
private static class MyDict<T>
{
public static Dictionary<TypeDict, T> Values { get; private set; }
static MyDict()
{
Values = new Dictionary<TypeDict, T>();
}
}
}
Now we can use the TypeDict like this:
void X()
{
var a = new TypeDict();
var b = new TypeDict();
a.Set<int>(1);
a.Set<double>(3.14);
a.Set("Hello, world!");
//Note that type inference allows us to omit the type argument
b.Set(10);
b.Set(31.4);
b.Set("Hello, world, times ten!");
Console.WriteLine(a.Get<int>());
Console.WriteLine(a.Get<double>());
Console.WriteLine(a.Get<string>());
Console.WriteLine();
Console.WriteLine(b.Get<int>());
Console.WriteLine(b.Get<double>());
Console.WriteLine(b.Get<string>());
}
Ark-kun is using generics to essentially generate unique types at compile time. With a generic type, any static members are unique to that specific closed generic type. This way it's processed as fast as a standard static member lookup.
The above usage is equivalent to something like this:
public static class MyDict_String
{
public static string Value { get; set; }
}
public static class MyDict_Int32
{
public static int Value { get; set; }
}
MyDict_String.Value = MyDict_Int32.Value.ToString();
AFAIK, types are "static" (in that you can't define more than one that way) so I don't know of a way to cheat around this and maintain the same performance of a statically compiled member lookup.
Your best bet otherwise (I think) is to create a generic instance type that wraps its own dictionary that uses System.Type for its keys and System.Object for its values to which you have to perform boxing/casting when inserting/retrieving values.
EDIT: Here's a simple implementation wrapping a dictionary:
public class MyTypedDict
{
private Dictionary<Type, object> Values = new Dictionary<Type, object>();
public T Get<T>()
{
object untypedValue;
if (Values.TryGetValue(typeof(T), out untypedValue))
return (T)untypedValue;
return default(T);
}
public void Set<T>(T value)
{
Values[typeof(T)] = value;
}
}
Thinking about it more, it might be possible to achieve a more property-like syntax using an ExpandoObject (http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject.aspx) through some tomfoolery, but I feel like this would be pretty abusive and I can only assume terribly prone to runtime errors. (plus it would afford you nothing at compile time)
EDITx2: If you really want to have different sets of values, you could nest it within another generic type:
public static class ValueSets<T>
{
public static class MyDict<U>
{
public static U Value { get; set; }
}
}
With usage like:
ValueSets<int>.MyDict<string>.Value = "Hello ";
ValueSets<bool>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<int>.MyDict<string>.Value + ValueSets<bool>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
But then the initial type int and bool in this case become "magical" and without meaning, plus you would need to provide a unique type per distinct set of values you'd like to use. Plus you could not pass it around and modify as an instance variable, rather it'd be statically accessible (so long as you have access to use the type T). So perhaps you could declare minimally visible types that are named with meaning and use those:
internal class MyFirstWords {}
internal class MySecondWords {}
ValueSets<MyFirstWords>.MyDict<string>.Value = "Hello ";
ValueSets<MySecondWords>.MyDict<string>.Value = "World!";
string helloworld = ValueSets<MyFirstWords>.MyDict<string>.Value + ValueSets<MySecondWords>.MyDict<string>.Value;
Console.WriteLine(helloworld);//Hello World!
Regardless, I think this is quite wacky and I wouldn't recommend it.
A more complicated version. Don't know if it's closer:
Define a generic dictionary:
public class MyDictionary<T>
{
Dictionary<string, T> dict;
public MyDictionary()
{
dict = new Dictionary<string, T>();
}
public T this[string name]
{
get
{
if (dict.ContainsKey(name))
return dict[name];
else
return default(T);//or throw
}
set
{
dict[name] = value;
}
}
}
Then a repository to store those dictionaries:
public class MyRepository
{
List<object> repo;
public MyRepository()
{
repo = new List<object>();
}
public void Add<T>(string name, T value)
{
if (!repo.OfType<MyDictionary<T>>().Any())
repo.Add(new MyDictionary<T>());
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
dict[name] = value;
}
public T GetValue<T>(string name)
{
if (!repo.OfType<MyDictionary<T>>().Any())
return default(T);//or throw
else
{
var dict = repo.OfType<MyDictionary<T>>().FirstOrDefault();
return dict[name];
}
}
}
And finally you may use this repository:
MyRepository repo = new MyRepository();
repo.Add("A", 1);
repo.Add("B", 1);
int i = repo.GetValue<int>("A") + repo.GetValue<int>("B");
In this example, there is MyDictionary<T> boxing to object is left.
From the other side, if your are working with some certain types you may not use thie repository class at all. But utilize separate dictionaties.
MyDictionary<int> intDict = new MyDictionary<int>();
intDict["A"] = 1;
intDict["B"] = 2;
int i = intDict["A"] + intDict["B"];
However it's the same as working with
Dictionary<string, int> intDict = new Dictionary<string, int>();
So the MyRepository class may be edited to use Dictionary<string, T> instead of MyDictionary<T>.
#Konstantin's answer made me remember that there is actually a very fast lookup method - array indexing. This crude PoC code shows a variant of the required structure.
public class TypeDictionary {
static int _maxId = 0;
int _id;
static class Store<T>{
internal static List<T> Values = new List<T>();
}
public TypeDictionary() {
_id = _maxId++;
}
public T GetValue<T>() {
return Store<T>.Values[_id];
}
public void SetValue<T>(T value) {
while(Store<T>.Values.Count < _id) {
Store<T>.Values.Add(default(T));
}
Store<T>.Values[_id] = value;
}
}
This code can be used as follows:
var dict1 = new TypeDictionary();
dict1.SetValue("my string");
string result = dict1.GetValue<string>();
The problem with this solution is it's memory usage caused by the repository being not sparse. This also makes first time value setting more expensive.
Try this:
public class MyDictionary
{
List<object> values;
public MyDictionary()
{
values = new List<object>();
}
public T GetValue<T>()
{
return values.OfType<T>().FirstOrDefault();
}
public bool Add<T>(T value)
{
if (values.OfType<T>().Any())
return false;
else
{
values.Add(value);
return true;
}
}
}
and use it:
var md = new MyDictionary();
md.Add("!!!");
string s = md.GetValue<string>();
This class may store up to one value of type T. But there could corner cases with derived classes and interfaces I guess. You may check, if it suits your need, and probably modify it as you need, if it's close to what you need in general.
What you are looking for is impossible in C#. The language does not support a container that could store multiple objects of different types yet provides a look up method that does not involve casting, boxing or unboxing. You could accomplish something like this with macros in C++, or via a language like javascript where the structure of types can be changed at run-time.
The usage case you are describing fits quite closely with the purpose for which ConditionalWeakTable<TKey,TValue> was added to .NET 4.0. For the purpose you describe, you would include such a table in a static generic class, and then for every class object that's supposed to contain a reference to an item of a particular type you would store into that type's table a reference to object that's supposed to contain the item along with either a reference to the item, or else a reference to a simple item-holder object (note that entries in ConditionalWeakTable will evaporate when an object ceases to exist, but are otherwise immutable, so if you want a mutable association you'll need to create an object to hold it).
Building on #phoog's example with #supercat's suggestion
public class TypeDict
{
public T Get<T>() where T : class
{
T value;
InnerDict<T>.Values.TryGetValue(this, out value);
return value;
}
public void Set<T>(T value) where T : class
{
var cwt = InnerDict<T>.Values;
// lock+remove+add https://github.com/dotnet/coreclr/issues/4545
lock (cwt)
{
cwt.Remove(this);
cwt.Add(this, value);
}
}
private static class InnerDict<T> where T : class
{
public static ConditionalWeakTable<TypeDict, T> Values { get; private set; }
static InnerDict()
{
Values = new ConditionalWeakTable<TypeDict, T>();
}
}
}
I'm trying to implement a simple plugin system which will allow people to write the following:
[Plugin("A plugin function")]
public static int PluginFunction(int a, int b)
{
return a + b;
}
and then drop the DLL containing this function into a folder where it will be scanned by the application and show up as an available function at runtime. This all works fine, so far so good, the PluginAttribute class is what you would expect, just a description string for the function.
However, I'd like to allow the plugin writer to specify default values for the parameters. This is OK for values which are constant at compile time and then deduced via reflection, but I'd like a way to specify defaults for more complex types which will be created at runtime. Has anyone implemented something similar? The primary goal is to make it simple to implement plugin functions - I'm trying to avoid complex scaffolding but accept that my nice simple system is not going to cut it if I want this feature. I'm also happy to have some complexity in the application code which makes the system appear simple to the plugin writer.
Thanks,
Charlie.
Update:
I'm going with a combination of what's been suggested here, the closest is what Peter O. came up with - here's a version:
[Plugin("A plugin function")]
[Defaults(typeof(AdderDefaults))]
public static int Adder(int a, int b)
{
return a + b;
}
public static class AdderDefaults
{
public static int a { get { return 1; } }
public static int b { get { return 2; } }
}
[Plugin("Another plugin function")]
[Defaults(typeof(TexturizerDefaults))]
public static Bitmap Texturize(Bitmap source, Point offset)
{
return result;
}
public static class TexturizerDefaults
{
// no default for source parameter
public static Point offset { get { return new Point(16, 16); } }
}
This allows parameters to be skipped and specified by name. No compile time checking but that's OK - checking these at runtime is acceptable.
Maybe you can create an attribute which refers to a type
containing default values for the plugin. Example:
[PluginDefaults(typeof(MyPluginDefaults))]
The class MyPluginDefaults could then look like:
public class MyPluginDefaults {
int Parameter1 { // First parameter
get { return 0; } // default value for 'a'
}
int Parameter2 { // Second parameter
get { return 4; } // default value for 'b'
}
// Additional parameters would be called Parameter3, Parameter4, and so on.
}
There are lots of way to do that, the simpliest is to use a simple convention :
[Plugin("A plugin function")]
public static int PluginFunction(int a, int b)
{
return a + b;
}
public static object[] PluginFunctionDefaultArguments()
{
return new [] { 0, 0 };
}
Each time you find a function marked with PluginAttribute search for a function having the same name with the DefaultArguments sufix, no parameters and an object[] return type. Then call it and store the values somewhere. You should also support the default values to be specifed using the dedicated C#/VB syntax (it is found in the DefaultValue member for the parameter)
One way would be to have property Defaults for each of the classes. It returns an object that can be queried for the defaults, for example like this:
object[] pluginFunctionDefaults = FooPlugin.Defaults["PluginFunction"];
(Obviously, you wouldn't have code exactly like this in your application.)
And the declaration of the defaults could look like this:
class FooPlugin
{
static FooPlugin()
{
var bar = new Bar();
Defaults = new DefaultValues()
.Add(() => PluginFunction(42, 13))
.Add(() => AnotherFunction(bar));
}
public static DefaultValues Defaults { get; private set; }
// actual methods of the class
}
Using expressions like this means that the types of the defaults are checked at compile time. The DefaultValues class parses the expressions and stores the parameters. It could look something like this:
class DefaultValues
{
private readonly Dictionary<string, object[]> m_expressions =
new Dictionary<string, object[]>();
public DefaultValues Add<T>(Expression<Func<T>> func)
{
var methodCall = ((MethodCallExpression)func.Body);
var name = methodCall.Method.Name;
var arguments =
methodCall.Arguments
.Select(Evaluate)
.ToArray();
m_expressions.Add(name, arguments);
return this;
}
private static object Evaluate(Expression expression)
{
return Expression.Lambda<Func<object>>(
Expression.Convert(expression, typeof(object)))
.Compile()();
}
public object[] this[string methodName]
{
get { return m_expressions[methodName]; }
}
}
I have the following enum:
public enum SymbolWejsciowy
{
K1 , K2 , K3 , K4 , K5 , K6 , K7 , K8
}
I want to create a list using the values of this enum:
public List<SymbolWejsciowy> symbol;
I have tried a couple different ways to add the enum values to the list:
SymbolWejsciowy symbol;
symbol.Add(symbol = SymbolWejsciowy.K1);
and
symbol.Add(SymbolWejsciowy.K1);
However, I always get the following exception:
Object reference not set to an instance of an object.
How can I correctly accomplish this?
As other answers have already pointed out, the problem is that you have declared a list, but you haven't constructed one so you get a NullReferenceException when you try to add elements.
Note that if you want to construct a new list you can use the more concise collection initializer syntax:
List<SymbolWejsciowy> symbols = new List<SymbolWejsciowy>
{
SymbolWejsciowy.K1,
SymbolWejsciowy.K2,
// ...
};
If you want a list containing all the values then you can get that by calling Enum.GetValues:
List<SymbolWejsciowy> symbols = Enum.GetValues(typeof(SymbolWejsciowy))
.Cast<SymbolWejsciowy>()
.ToList();
In your option 1 SymbolWejsciowy instance and your list have the same name, I imagine that's a typo error.
Without taking that into account I'd say you didn't created the instance of the list
symbol = new List<SymbolWejsciowy>();
Your code never initializes the list. Try this:
public List<SymbolWejsciowy> symbol = new List<SymbolWejsciowy>();
symbol.Add(SymbolWejsciowy.K1);
and
SymbolWejsciowy mySymbol= SymbolWejsciowy.K2;
symbol.Add(mySymbol);
It sure would be nice if Enum.GetValues() had been updated for generics way back in C# 2.0. Well, guess we have to write it ourselves:
static class EnumHelpers<T> where T : struct
{
public class NotAnEnumException : Exception
{
public NotAnEnumException() : base(string.Format(#"Type ""{0}"" is not an Enum type.", typeof(T))) { }
}
static EnumHelpers()
{
if (typeof(T).BaseType != typeof(Enum)) throw new NotAnEnumException();
}
public static IEnumerable<T> GetValues()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
public static T Parse(string value)
{
return (T)Enum.Parse(typeof(T), value);
}
}
I included Parse() because it benefits from generics in the same way.
Usage:
var symbols = EnumHelpers<SymbolWejsciowy>.GetValues().ToList();
SymbolWejsciowy s = EnumHelpers<SymbolWejsciowy>.Parse("S2");
(ASIDE: I also wish you could write where T : enum for just this sort of thing. Also, where T : delegate.)
None of these answers worked for me.
I think most people just want a List<string> or list of values after combining many enums together. This should help:
static class MyPets {
enum Cats
{
Felix,
Hairy,
TunaBreath
}
enum Dogs
{
Fido,
Fred,
Butch
}
public static void PrintPets() {
List<string> Pets = new List<string>();
Pets.AddRange(Enum.GetNames(typeof(Cats)).ToList());
Pets.AddRange(Enum.GetNames(typeof(Dogs)).ToList());
foreach(string p in Pets){
Console.WriteLine(p);
}
}
}
// RESULT
Felix
Hairy
TunaBreath
Fido
Fred
Butch