How can I avoid code repetition with enums in C#? - c#

I am populating three list boxes with values from three corresponding enums. Is there some way to avoid having three separate-but-very-similar methods? Here's what I have now:
private void PopulateListBoxOne()
{
foreach (EnumOne one in Enum.GetValues(typeof(EnumOne)))
{
lstOne.Items.Add(one);
}
lstOne.SelectedIndex = 0;
}
private void PopulateListBoxTwo()
{
foreach (EnumTwo two in Enum.GetValues(typeof(EnumTwo)))
{
lstTwo.Items.Add(two);
}
lstTwo.SelectedIndex = 0;
}
private void PopulateListBoxThree()
{
foreach (EnumThree three in Enum.GetValues(typeof(EnumThree)))
{
lstThree.Items.Add(three);
}
lstThree.SelectedIndex = 0;
}
But I'd instead prefer to have one method (which I could call three times) looking something like:
private void PopulateListBox(ListBox ListBoxName, Enum EnumName)
{
// ... code here!
}
I'm quite an inexperienced programmer, so although I did search, I wasn't quite sure what I was searching for. Apologies if this has been answered before; I'd be equally grateful to be shown an existing answer. Thanks!

You need to pass enum type to your method
private void PopulateListBox(ListBox ListBoxName, Type EnumType)
{
foreach (var value in Enum.GetValues(EnumType))
{
ListBoxName.Items.Add(value);
}
ListBoxName.SelectedIndex=0;
}
so call it like:
PopulateListBox(lstThree,typeof(EnumThree));

You could use a generic method:
private void PopulateListBox<TEnum>(ListBox listBox, bool clearBeforeFill, int selIndex) where TEnum : struct, IConvertible
{
if (!typeof(TEnum).IsEnum)
throw new ArgumentException("T must be an enum type");
if(clearBeforeFill) listBox.Items.Clear();
listBox.Items.AddRange(Enum.GetNames(typeof(TEnum))); // or listBox.Items.AddRange(Enum.GetValues(typeof(TEnum)).Cast<object>().ToArray());
if(selIndex >= listBox.Items.Count)
throw new ArgumentException("SelectedIndex must be lower than ListBox.Items.Count");
listBox.SelectedIndex = selIndex;
}
How you use it:
PopulateListBox<EnumThree>(lstThree, true, 0);

You could try something like
private List<T> PopulateList<T>()
{
List<T> list = new List<T>();
foreach (T e in Enum.GetValues(typeof(T)))
{
list.Add(e);
}
return list;
}

Related

How to use generic type in a value tuple?

Let's presume i have two enums:
public enum eFruits : int
{
Apple = 1,
Pear = 2,
Banana = 3
}
public enum eAnimals : int
{
Dog = 1,
Cat = 2,
Rabbit = 3
}
I would like to use these in dropdownlists/checklists etc; basically as listitems. The current code i have as a tryout is this;
public static class EnumHelper
{
public static IEnumerable<(int eCode, eFruits eType)> GetFruitTypesAsListItems()
{
var enums = new List<(int eCode, eFruits eType)>();
foreach (var item in (eFruits[])Enum.GetValues(typeof(eFruits)))
{
enums.Add(((int)item, item));
}
return enums;
}
}
Two issues with this;
1) I would like to have this in a generic way
2) It doesn't look nice inside a list/dropdown etc. so I'd like to use a ToString override.
Therefore I thought of something like this:
public class EnumListItem : Tuple<int, T>
{
public EnumListItem(int eCode, T eType)
: base(eCode, eType)
{ }
public override string ToString() => $"{base.Item2.ToString()} ({base.Item1})";
}
So in effect;
1) I would like to use a Generic with a Tuple
2) Would like to use a Generic to be able to generate list items based on that Tuple
Is this possible? I'm not sure how the declaration of this would look like. At this point I can't get it to work. Can someone point me in the right direction?
You can try below generic method.
public static class EnumHelper<T>
{
public static IEnumerable<(int eCode, T eType)> GetListItem()
{
var enums = new List<(int eCode, T eType)>();
foreach (var item in (T[])Enum.GetValues(typeof(T)))
{
enums.Add((Convert.ToInt32(item), item));
}
return enums;
}
}
And you can call it like,
public static void Main(string[] args)
{
var animals = EnumHelper<eAnimals>.GetListItem();
var fruits = EnumHelper<eFruits>.GetListItem();
}
Output:
It is quite simple to make it a generic function. And you could use yield to return a generator enumerable instead of a buffered List to get rid of unnecessary use of memory.
public static IEnumerable<(int, TEnum)> GetValues<TEnum>()
where TEnum : struct, Enum
{
foreach (var item in Enum.GetValues(typeof(TEnum)))
{
yield return ((int)item, (TEnum)item);
}
}

C# - check if List<> is initialized

I have function that accept out List<int> list as parameter. How can I check if list is initialized or not?
This code gives me the Use of unassigned out parameter 'list' error:
public void CheckList(out List<int> list)
{
if (list == null) {
list = List<int>();
}
//Rest of the code
}
Facts that I have checked:
Variables passed as out arguments do not have to be initialized before being passed in a method call. However, the called method is
required to assign a value before the method returns. out parameter
modifier
Edit:
I want my method to be able to accept both options: list with elemtns and append aditional elements to it or in other case to initialize list and add elements to it.
If you are dealing with out argument then most certainly it isn't initialized because the method should initialize it.
If it was passed by "ref", then you would check it.
Why not use a wrapper?
public void CheckListWrapper(ref List<int> list)
{
if(list == null)
{
CheckList(out list);
}
else
{
//append whatever
}
}
public void CheckList(out List<int> list)
{
list = List<int>();
//Rest of the code
}
I added a new parameter for sameList and it will work for you so
what about this one. There is no more way to accept without Initialization.
private static void Main()
{
List<int> i=null;
CheckList(out i,i);
Console.WriteLine(i[0]);
}
public static void CheckList(out List<int> list,List<int> sameList)
{
list = sameList;
if(list==null)
{
//Intialize
list = new List<int>();
list.Add(1);
}
else
{
//append
list.Add(12);
}
//Rest of the code
}
Try the following code:
bool IsInitialised(List myList) {
if ( (myList!= null) && (!myList.Any()) )
{
return true;
}
return false;
}
A linq-less way will be:
if(myList != null && myList.Count == 0){
// The list is empty. Add something here
}
From your calling method like Main:
Pseudo code. Testmethod(ref list) and TestMethod(list) have different signature so they both compile.
if(IsInitialised(list))
Call TestMethod(ref list);
Else call TestMethod(list);

How can I prevent duplication of a common loop in my solution?

I have this loop based on a jagged array below which I will need to use more than once at different places.
How can I prevent myself to rewrite this loop again and again so that I will duplicate it?
foreach (int[] columns in rowsAndColumns)
{
foreach (int element in columns)
{
}
}
You can write
foreach (int element in rowsAndColumns.SelectMany(col => col))
{
// ...
}
instead. If you don’t like to have to type that all the time, you can abstract it into a helper method:
foreach (int element in rowsAndColumns.Flatten())
{
// ...
}
// [...]
public IEnumerable<T> Flatten(this IEnumerable<IEnumerable<T>> source)
{
return source.SelectMany(e => e);
}
It depends on what you want to do, but if you want to perform an action on each int, you could go for something like the extension below. Some null checking might be advisible.
static class RowColExtension
{
public static void Each(this int[][] rowCols, Action<int> a)
{
foreach (var r in rowCols)
{
foreach (var c in r)
{
a(c);
}
}
}
}
It depends on what you want to do in the loop. I would approach it like this (untested code out of my head!):
public static class MyHelper {
public static void ForEach(this IEnumerable<int[]> rowsAndColumns, Action<int> action) {
foreach (int[] columns in rowsAndColumns) {
foreach (int element in columns) {
action(element);
}
}
}
}
Now you can call it like this:
rowsAndColumns.ForEach(e => Console.WriteLine(e));
Extension method:
// It's late and I'm tired, the array declaration might be off.
public static void Visit(this int[][] array, Action<int> visitor)
{
foreach (int[] columns in array)
{
foreach (int element in columns)
{
visitor(element);
}
}
}
myArray.Visit(elem => Console.WriteLine(elem));
You can use Action<int,int> to get the row too.
Since you are iterating over all elements without regard to the row or column you should turn your jagged array into a first class data structure and implement IEnumerable to iterate over the collection using foreach. The same first-class data structure can support one-argument and two-argument indexers, range checking, etc.
Edit:
Here is one approach to use abstraction instead of manipulating low-level data structures. This assumes the jagged array was allocated elsewhere. Either way, the point is we can now use foreach directly on the data structure:
public class JaggedArray : IEnumerable<int>
{
private int[][] array;
public JaggedArray(int[][] array)
{
this.array = array;
}
public int this[int row, int column]
{
get { return array[row][column]; }
set { array[row][column] = value; }
}
public IEnumerable<int[]> Rows
{
get { return array; }
}
public IEnumerator<int> GetEnumerator()
{
foreach (var row in array)
foreach (var item in row)
yield return item;
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

Problem with casting x<char> to x<t>

Hey guys I cant manage with this code. The idea is to return default English alphabet in case of erroneous create method execution. Thanks.
An idea to override explicit operator is good, but i cant imagine an implementation of casting.
namespace trie
{
class AlphabetFactory<T> where T: IConvertible
{
public Alphabet<char> SetDefaultAlphabet()
{
var list = new char[26];
for (var i = Convert.ToInt32('a'); i <= Convert.ToInt32('z'); i++)
list[i] = Convert.ToChar(i);
return new Alphabet<char>(list);
}
public Alphabet<T> Create(params T[] list)
{
if (list != null)
return new Alphabet<T>(list);
else
return SetDefaultAlphabet(); // <- This is not correct
}
}
}
The only way I can think to accomplish what you want is to make Alphabet<T> inherit from a non-generic abstract base, or else implement a non-generic interface. Then your code might look something like this:
interface IAlphabet {
// ?
}
class Alphabet<T> : IAlphabet {
// stuff
}
class AlphabetFactory {
// ...
IAlphabet Create<T>(params T[] list) where T : IConvertible {
if (list != null)
return new Alphabet<T>(list);
else
return SetDefaultAlphabet();
}
// ...
}
This would make client code using your AlphabetFactory a bit more cumbersome to use, though:
int[] integers = GetIntegers(); // let's say this might be null
var alphabet = myAlphabetFactory.Create(integers);
var integerAlphabet = alphabet as Alphabet<int>;
if (integerAlphabet != null) {
// do stuff with integerAlphabet
} else {
// alphabet is an IAlphabet, but not an Alphabet<int>
}

In C# 3.0 is there any syntax for a block of code that will run only if a foreach doesn't have any iterations?

meaning something like...
foreach(blah b in blahblahs)
{
writeOnMoon(b.name);
}
default
{
writeOnMoon("No Blahs!");
}
default or, otherwise, or something like that, if this does not exist... do you think it should?
how about:
bool run = false;
foreach (var item in collection)
{
run = true;
// Do stuff
}
if (!run)
{
// Other Stuff
}
There isn't a keyword to do this.
You can do:
if (blahblahs.Any())
{
foreach(blah b in blahblahs)
{
writeOnMoon(b.name);
}
}
else
{
writeOnMoon("No Blahs!");
}
Couldn't you just check blahblahs.length first?
This doesn't exist.
I don't think this should be in the language because it really doesn't allow you to do anything new, nor does it make any current complex tasks much simpler.
No, but you could write an extension method so you could write:
collection.ForEachOrDefault(b =>
{
WriteOnMoon(b.name);
}, () =>
{
WriteOnMoon("No Blahs!");
});
Admittedly I don't think I'd recommend it... but here's the code:
public static void ForEachOrDefault<T>(this IEnumerable<T> source,
Action<T> forEachAction, Action defaultAction)
{
// Nullity checking omitted for brevity
bool gotAny = false;
foreach (T t in source)
{
gotAny = true;
forEachAction(t);
}
if (!gotAny)
{
defaultAction();
}
}
No, there is not.
Nope, there's no specific syntax in C# that will do what you want.
You're forced to devise your own approach (like what JDunkerley's example shows).
Python has this (for ... else ...) and I really miss it in C#.
With LINQ you can do something like this:
public static IEnumerable<T> IfEmpty<T>(this IEnumerable<T> source, Action action)
{
var enumerator = source.GetEnumerator();
if (enumerator.MoveNext())
do yield return enumerator.Current; while (enumerator.MoveNext());
else
action();
}
mylistofobjects.Each(...).IfEmpty(() => { /* empty list */ });
No. But you can try to invent a simple extension method - for simple cases it will do...
public static class EnumerableExtension
{
public static void IfEmpty<T>(this IEnumerable<T> list, Action<IEnumerable<T>> action)
{
if (list.Count() == 0)
action(list);
}
}
foreach (var v in blabla)
{
}
blabla.IfEmpty(x => log("List is empty"));
Maybe you'll even be able to create re-usable actions then. Though it doesn't really make much sense.
IEnumerable myCollection = GetCollection();
if(myCollection.Any())
{
foreach(var item in myCollection)
{
//Do something
}
}
else
{
// Do something else
}

Categories