How to add enum values to a list - c#

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

Related

How do I return all items in a collection that possess an interface property of a specific type?

I have a class ApprovalTicket that has a property called ApprovalRules that is of type IApproval:
IApproval ApprovalRules;
This field will contain several different types of classes that implement that interface. Now stepping one level up, I will have a List of ApprovalTickets. What I'm trying to do is use linq to return a list of ApprovalTickets that have ApprovalRules of the type MocReviewerApproval.
I was trying something like:
var reviews = request.MocApprovalTasks
.Where(mocApproval => mocApproval.ApprovalRules is MocReviewerApproval)
.ToList();
But when I check the list that gets returned, it's still including tickets that have an ApprovalRules type of MocManagerApproval and others as well. What am I missing?
UPDATE:
Let me be more specific. Here is the inheritance scheme
MocApproval : TaskTicket
>>IApproval ApprovalRules;
MocReviewerApproval : IApproval
MocManagerApproval : IApproval
MocControllerApproval : IApproval
internal interface IApproval
{
bool Approve(Guid approverGuid, MocApproval approval);
bool Deny(Guid approverGuid, MocApproval approval, TaskComment denialComment);
bool Close(Guid approverGuid, MocApproval approval, TaskComment closeComment);
bool Notify();
void Set(MocApproval approval);
User GetAssignee();
TaskComment GetNotificationComment();
}
is means, can be validly cast to, not, "is exactly this type". In your case, any sub-classes of MocReviewerApproval will still return true. You can use:
mocApproval.ApprovalRules.GetType() == typeof(MocReviewerApproval)
to ensure that that type, and only that type, will return true. Having said that, it's kinda bad code smell to have something like this. Consider asking yourself if that's really what you want.
Your code looks fine to me. I suspect you've got diagnostic problems, or you're not after the is kind of relationship at all. Here's a complete example showing it working:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
class Foo
{
public object Value { get; set; }
}
class Test
{
static void Main()
{
var list = new List<Foo>
{
new Foo { Value = "" },
new Foo { Value = 10 },
new Foo { Value = new object() },
new Foo { Value = new MemoryStream() }
};
ShowCount<IDisposable>(list); // 1 (MemoryStream)
ShowCount<IFormattable>(list); // 1 (Int32)
ShowCount<IComparable>(list); // 1 (String, Int32)
}
static void ShowCount<T>(List<Foo> list)
{
var matches = list.Where(f => f.Value is T)
.ToList();
Console.WriteLine("{0} matches for {1}",
matches.Count, typeof(T));
}
}
EDIT: If you want matches which are exactly the given type, use:
var reviews = request.MocApprovalTasks
.Where(task => task.ApprovalRules.GetType() ==
typeof(MocReviewerApproval))
.ToList();
That's more refactoring-friendly than finding the name as per Servy's original answer.

WCF. IList is deserialized as array. How to make it be any writable list (ArrayList)?

I have a client-server application, parts of which "talk" to each other through WCF (netTcp binding).
I have my DataContract, which has 1 field of a 3rd party class:
[Serializable]
public class MyResult{
public ThirdPartyResult Result {get;set;}
/* other fields */
}
Using reflection i see this:
[Serializable]
public class ThirdPartyResult {
private IList result;
public IList Result
{
get { return result ?? (result = new ArrayList());}
}
}
When calling the server from client I have the result as ArrayList on server. After it comes to client the result field becomes a fixed size array.
I didn't use Add service reference, but i use assembly sharing and just do
ChannelFactory<IMyContract>.CreateChannel(new NetTcpBinding("Configuration.Name"), address);
UPDATE: the service contract
[ServiceContract]
[ServiceKnownType(typeof(ArrayList))]
[ServiceKnownType(typeof(ThirdPartyResult))]
public interface IMyContract
{
MyResult GetResult();
}
Now the question:
How can I tell WCF to use ArrayList instead of Array?
I came up with a very bad solution (from my point of view)
Generally I wanted an ArrayList to be preserved to be able to add items to it. Finally I came up with the solution below. Yes, I know, this is completely bad, and that's why I'm still looking for some better variant.
if (thirdParty.Results != null && thirdParty.Results.IsFixedSize)
{
var results = new ArrayList(thirdParty.Results);
// Finding result by ReferenceEquals to not be tight to private variable name
var resultsField = thirdParty.GetType()
.GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic)
.Where(f => ReferenceEquals(f.GetValue(thirdParty), thirdParty.Results))
.FirstOrDefault();
if (resultsField != null)
resultsField.SetValue(thirdParty, results);
}
thirdParty.AddResult(otherChild);
When you create a new Service Reference (or configuring an existing reference) in the Visual Studio there is a property something like "Deserialize arrays as" and there you can choose array/list/etc. You could take a look at the generated code and change your code to achieve what you want.
Please see the following:
WCF: Serializing and Deserializing generic collections
This solved my problem: Both the private member and custom property method work for me.
[DataMember]
private List<Person> members = new List<Person>();
OR change the property to:
[DataMember]
private Iist<Person> members = new Iist<Person>();
[DataMember()]
public IList<Person> Feedback {
get { return m_Feedback; }
set {
if ((value != null)) {
m_Feedback = new List<Person>(value);
} else {
m_Feedback = new List<Person>();
}
}
}
Ultimately your contract contains no information that would make it choose any particular implementation. The best way to fix this would be; to make result well-typed, perhaps as ArrayList:
private ArrayList result;
public IList Result {
get { return result ?? (result = new ArrayList());}
}
personally I'd hope to see a List<T> with [DataContract]/[DataMember] etc, but...
if nothing else then I would write an extension class to extend ThirdPartyResult
public static class ThirdPartyResultExtension
{
public static ArrayList ResultsAsArrayList(this ThirdPartyResult d)
{
ArrayList list = new ArrayList();
list.AddRange(d.Result);
return list;
}
}
public class ThirdPartyResult
{
private IList result;
public IList Result
{
get { return result ?? (result = new ArrayList()); }
}
}
and use it like
ThirdPartyResult r;
ArrayList arrlist = r.ResultsAsArrayList();

C#: Class return value - or is there a better way?

I created a class that had one member of type List. I could then add to this using ClassNameInstance.Add().
We are now using some code from a third-party that will automatically use any class I create and its values. Except lists. It only returns the first element in the list.
What I need is a comma-separated version returned instead for this third-parties code to use. Now I could just append the Strings to a String member, but this doesn't look as nice as the .Add() method.
So I wanted to create my own Class that I could have an Add() method for but could access its single value like so:
MyClass1.Add("Test1");
MyClass1.Add("Test2");
Console.WriteLine(MyClass2);
The output I would like would be Test1, Test2. I hope this makes sense!
UPDATE1:
Seems the above may not have been clear.
public class MyClass1
{
????
}
public class MyClass2
{
MyClass1 mc1 { get; set; }
String name { get; set; }
}
The third party code will use MyClass2 and its assigned values. When I used List instead of MyClass1 I only get the first value in the list, but need a CSV list as a String returned.
MyClass2 mc2 = new MyClass2();
mc2.mc1.Add("Test1");
mc2.mc1.Add("Test2");
Console.WriteLine(mc2.mc1) should output -> Test1, Test2
Hope that clears things up some more!
Thanks everyone! :)
UPDATE2:
It seems everyone is suggesting the same thing - use ToString().
Unfortunately, the third-party code will look at my class and determines the members type and value automatically. This means that I am not able to pass the code the value that would be returned by calling ToString().
I kind of need the add/remove functionality of a List<> but when used its value returns as a single CSV string.
I'm not sure that you need an extra class here:
List<string> list = new List<string>();
list.Add("Test1");
list.Add("Test2");
Console.WriteLine(string.Join(", ", list.ToArray());
You could wrap this behaviour in a class just to get it automatically invoked on ToString:
public sealed class StringJoiningList
{
private readonly List<string> list = new List<string>();
public void Add(string item)
{
list.Add(item);
}
public override string ToString()
{
return string.Join(", ", list.ToArray());
}
}
Now that's assuming you just want a List<string> - it also doesn't let you access the items other than by the ToString() method. All of that is fixable of course, if you could give more information. You could even just derive from List<T>:
public class StringJoiningList<T> : List<T>
{
public override string ToString()
{
return string.Join(", ", this.Select(x => x.ToString()).ToArray());
}
}
I'm not entirely sure I like the idea, but it depends on what you need to do...
A couple of easy options would be to override the ToString() method of your class (so that when it is used in this context it returns a comma-delimited list of items) or you can provide a property that flattens the list.
You need to implement the ToString method.
Here's an extension I wrote to join the items in an IEnumerable<T>
public static string Join<T>(this IEnumerable<T> collection,
string separator, Func<T, object> selector)
{
if (null == separator)
throw new ArgumentException("separator");
if (null == selector)
throw new ArgumentException("selector");
Func func = item =>
{
var #object = selector(item);
return (null != #object) ? #object.ToString() : string.Empty;
};
return string.Join(separator, collection.Select(func).ToArray());
}
It can be used like this:
List<Person> list = new List<Person>()
{
new Person() { FirstName = "Magic", LastName = "Johnson" },
new Person() { FirstName = "Michael", LastName = "Jordon" },
new Person() { FirstName = "Larry", LastName = "Bird" }
};
var value = list.Join(", ", p => p.FirstName);
// value is "Magic, Michael, Larry"
Not really the answer I wanted, but it seems that I couldn't do what I wanted.
In the class where I wanted to have my second class as a member, I made that member a String so the third-party code would work as I wanted.
I created a second class that had a List<String> as a public member and then a Method called .ToCSV() to output the list as a csv string. I added a .Add() method to add the strings to the list to save having to go Class1.Class2.Add().
Then just before the third-party code would use my class, I do:
MyClass1.MyString = MyClass2.ToCSV();
Thus giving me basically what I wanted in a round about way!!
Thanks for everyone's input and help!
Neil
The simplest solution is probably to inherit from the StringCollection class and just override ToString. Otherwise this class already has everything you are asking about.
public class MyClass : System.Collections.Specialized.StringCollection
{
public override string ToString()
{
var c = new string[this.Count];
this.CopyTo(c,0);
return string.Join(",", c);
}
}
Then you can use it just like you were trying to before. No need to get fancy with generics for this simple usage.
Edit:
Classes themselves don't have a return value, so the 3rd party code must be reading properties. You should be able to override ToString() as described above then expose a property that returns the ToString(). That would probably make the string value visible to the 3rd party code
public class MyClass : System.Collections.Specialized.StringCollection
{
public string MyValue
{
get { return this.ToString(); }
}
public override string ToString()
{
var c = new string[this.Count];
this.CopyTo(c,0);
return string.Join(",", c);
}
}

sorting enum for UI purpose

Say we have a UI and in this UI we have a dropdown. This dropdown is filled with the translated values of an enum.
Bow, we have the possibility to sort by the int-value of the enum, by the name of the enum, and by the translated name of the enum.
But what if we want a different sorting than the 3 mentioned above. how to handle such a requirement?
Implement your own IComparer:
using System;
using System.Collections.Generic;
namespace test {
class Program {
enum X {
one,
two,
three,
four
}
class XCompare : IComparer<X> {
public int Compare(X x, X y) {
// TBA: your criteria here
return x.ToString().Length - y.ToString().Length;
}
}
static void Main(string[] args) {
List<X> xs = new List<X>((X[])Enum.GetValues(typeof(X)));
xs.Sort(new XCompare());
foreach (X x in xs) {
Console.WriteLine(x);
}
}
}
}
You can use the Linq extension OrderBy, and perform whatever comparison magic you want:
// order by the length of the value
SomeEnum[] values = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));
IEnumerable<SomeEnum> sorted = values.OrderBy(v => v.ToString().Length);
Then wrap the different sorting alternatives into methods, and invoke the right one based on user preferences/input.
IEnumerable<T>.OrderBy(Func<T, TKey>, IComparer<TKey>)
Sort FileSystemRights enum using Linq and bind to WinForms comboBox:
comboBox1.DataSource = ((FileSystemRights[])Enum.GetValues(typeof(FileSystemRights))).
OrderBy(p => p.ToString()).ToArray();
Perhapse you could create an extension method for the Enum class, like this:
... first the declaration...
public enum MyValues { adam, bertil, caesar };
...then in a method...
MyValues values = MyValues.adam;
string[] forDatabinding = values.SpecialSort("someOptions");
...The extension method...
public static class Utils
{
public static string[] SpecialSort(this MyValues theEnum, string someOptions)
{
//sorting code here;
}
}
And you could add different parameters to the extension metod for different sort options etc.

Shortcut for creating single item list in C#

In C#, is there an inline shortcut to instantiate a List<T> with only one item.
I'm currently doing:
new List<string>( new string[] { "title" } ))
Having this code everywhere reduces readability. I've thought of using a utility method like this:
public static List<T> SingleItemList<T>( T value )
{
return (new List<T>( new T[] { value } ));
}
So I could do:
SingleItemList("title");
Is there a shorter / cleaner way?
Thanks.
Simply use this:
List<string> list = new List<string>() { "single value" };
You can even omit the () braces:
List<string> list = new List<string> { "single value" };
Update: of course this also works for more than one entry:
List<string> list = new List<string> { "value1", "value2", ... };
var list = new List<string>(1) { "hello" };
Very similar to what others have posted, except that it makes sure to only allocate space for the single item initially.
Of course, if you know you'll be adding a bunch of stuff later it may not be a good idea, but still worth mentioning once.
Michael's idea of using extension methods leads to something even simpler:
public static List<T> InList<T>(this T item)
{
return new List<T> { item };
}
So you could do this:
List<string> foo = "Hello".InList();
I'm not sure whether I like it or not, mind you...
A different answer to my earlier one, based on exposure to the Google Java Collections:
public static class Lists
{
public static List<T> Of<T>(T item)
{
return new List<T> { item };
}
}
Then:
List<string> x = Lists.Of("Hello");
I advise checking out the GJC - it's got lots of interesting stuff in. (Personally I'd ignore the "alpha" tag - it's only the open source version which is "alpha" and it's based on a very stable and heavily used internal API.)
new[] { "item" }.ToList();
It's shorter than
new List<string> { "item" };
and you don't have to specify the type.
Use an extension method with method chaining.
public static List<T> WithItems(this List<T> list, params T[] items)
{
list.AddRange(items);
return list;
}
This would let you do this:
List<string> strings = new List<string>().WithItems("Yes");
or
List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So");
Update
You can now use list initializers:
var strings = new List<string> { "This", "That", "The Other" };
See http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx
Yet another way, found on "C#/.Net Little wonders" (unfortunately, the site doesn't exist anymore):
Enumerable.Repeat("value",1).ToList()
For a single item enumerable in java it would be Collections.singleton("string");
In c# this is going to be more efficient than a new List:
public class SingleEnumerator<T> : IEnumerable<T>
{
private readonly T m_Value;
public SingleEnumerator(T value)
{
m_Value = value;
}
public IEnumerator<T> GetEnumerator()
{
yield return m_Value;
}
IEnumerator IEnumerable.GetEnumerator()
{
yield return m_Value;
}
}
but is there a simpler way using the framework?
I've got this little function:
public static class CoreUtil
{
public static IEnumerable<T> ToEnumerable<T>(params T[] items)
{
return items;
}
}
Since it doesn't prescribe a concrete return type this is so generic that I use it all over the place. Your code would look like
CoreUtil.ToEnumerable("title").ToList();
But of course it also allows
CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray();
I often use it in when I have to append/prepend one item to the output of a LINQ statement. For instance to add a blank item to a selection list:
CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name))
Saves a few ToList() and Add statements.
(Late answer, but I stumbled upon this oldie and thought this could be helpful)
Try var
var s = new List<string> { "a", "bk", "ca", "d" };
You can also do
new List<string>() { "string here" };
I would just do
var list = new List<string> { "hello" };
Inspired by the other answers (and so I can pick it up whenever I need it!), but with naming/style aligned with F# (which has a standard singleton function per data structure*):
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Singleton<T>(T value) => new List<T>(1) { value };
}
}
* except for ResizeArray itself of course, hence this question :)
In practice I actually name it Create to align with other helpers I define such as Tuple.Create, Lazy.Create[2], LazyTask.Create etc:
namespace System.Collections.Generic
{
public static class List
{
public static List<T> Create<T>(T value) => new List<T>(1) { value };
}
}
[2]
namespace System
{
public static class Lazy
{
public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory);
}
}
The declarations make it so easy now to do in C# 10.0 that I don't think theres a need for any helper. Just add the new(){} around any value you want to cast to a list.
List<string> values = new() { "single value" };
If someone landed on this page and trying to add object instead of string, then this worked for me.
new List<myObj> { new myObj{propertName=propstryValue }
, new myObj{propertName=propstryValue }, new myObj{propertName=propstryValue }
};
You need to create an inheritor from the List<> class
public class SingletonList<T> : List<T>
{
public SingletonList(T element) : base(1)
{
this.Add(element);
}
}
and you can use it instead of the base List<> class
var singletonList = new SingletonList<string>("Hello World!");

Categories