Cannot convert from 'string' to 'T' - c#

I have created a helper function which accepts a string array as input and the index of the column as selected output.
public static List<T> GetByIndex<T>(string[] data, int index)
{
List<T> list = new List<T>();
foreach (var item in data)
{
if (item.Contains("|"))
{
string[] s = item.Split("|");
list.Add(s[index]);
}
}
return list;
}
At line list.Add(s[index]); i get the error Cannot convert from 'string' to 'T'.
How can i make this method generic?
The function should return string or integer or even maybe boolean

How can i make this method generic?
You shouldn't. You're only dealing with strings so make the method return a List<string>
public static List<string> GetByIndex(string[] data, int index)
{
var list = new List<string>();
foreach (var item in data)
{
if (item.Contains("|"))
{
string[] s = item.Split("|");
list.Add(s[index]);
}
}
return list;
}
If you need to also support int then just make an overload which returns a List<int> and use int.Parse / int.TryParse.

It seems that you don't want generic T at all: what is the expected output for, say, T == IComparer<DateTime>?
I suggest getting rid of T and returning List<string>:
public static List<string> GetByIndex(string[] data, int index) {
// Public method's arguments validation
if (data is null)
throw new ArgumentNullException(nameof(data));
if (index < 0)
throw new ArgumentOutOfRangeException(nameof(index));
List<string> list = new List<string>();
foreach (string item in data) {
// Do not forget about nulls
if (item != null) {
// We can stop earlier on Split:
// if, say, index == 2 we don't want all 12345 items
string[] s = item.Split('|', index + 2);
// s can well be too short
if (s.Length > index)
list.Add(s[index]);
}
}
return list;
}

If you want to return a List<T>, you need to provide some way of converting each string into a T.
Such as:
public static List<T> GetByIndex<T>(
string[] data,
int index,
Func<string, T> convertItem)
{
List<T> list = new List<T>();
foreach (var item in data)
{
if (item.Contains("|"))
{
string[] s = item.Split("|");
list.Add(convertItem(s[index]));
}
}
return list;
}
And you could provide convenience overloads for the types you commonly use.
For example:
public static List<int> GetIntByIndex(string[] data, int index)
{
return GetByIndex(data, index, int.Parse);
}

Related

How to create IReadOnlyCollection<T> method that returns generic data

public static IReadOnlyCollection<int> FillData(this string[] ids, IReadonlyCollection<int> list)
{
var dataList = list?.ToList() ?? new List<int>();
foreach (var id in ids)
{
dataList.Add(int.Parse(id));
}
return datalist.AsReadOnly();
}
How to create Generic method in order to receive int and long for IReadOnlyCollection param and return the value based on requested type?
Something like that should work
public static IReadOnlyCollection<T> FillData<T>(this string[] ids, IReadOnlyCollection<T> list)
{
var dataList = list?.ToList() ?? new List<T>();
foreach (var id in ids)
{
dataList.Add((T)Convert.ChangeType(id, typeof(T)));
}
return dataList.AsReadOnly();
}
PS: But keep in mind maybe you have to consider the culture.

Set Values in Generic IEnumerable

I have a generic method that I want to pass a variable to, and if that variable is IEnumerable, set all its elements to its default value. This is what I have so far:
public static T set_to_default<T>(T the_obj)
{
var the_enumerable = the_obj as IEnumerable;
if (the_enumerable != null)
{
foreach (var element in the_enumerable)
{
// I don't know what to put here
// I want to set each element to its default value: default(T)
}
return the_obj;
}
else
{
return default(T);
}
}
What do I put inside the foreach loop?
You should just work with overloads, it's much simpler (if I understand your question correctly).
public static T SetToDefault<T>(T the_obj)
{
return default(T);
}
public static IEnumerable<T> SetToDefault<T>(IEnumerable<T> the_enumerable)
{
return the_enumerable.Select(value => default(T));
}
FYI I tested my code with this function:
public static void Test()
{
int myInt = 7;
IEnumerable<int> myEnumberable = new List<int>() { 1, 4, 8, 9 };
myInt = SetToDefault(myInt);
myEnumberable = SetToDefault(myEnumberable);
Console.WriteLine($"MyInt: {myInt}");
Console.WriteLine($"MyEnumberable: {String.Join(", ", myEnumberable)}");
}
To add to this, keep in mind that the name SetToDefault isn't a great choice. When you pass in an int, you will get back an int. You still have to set the value yourself (myInt = SetToDefault(myInt);) which is kind of contradictory to what the name of the function implies.
By the way, note that the first function (T SetToDefault<T>(T the_obj)) has a parameter which is never used. To work around this (to be fair, small) issue, you could use an extension method:
public static class Extensions {
public static T GetDefault<T>(this T value) {
return default(T);
}
}
Note that even here, you will have to set the value to the return of the function. Returning void and simply doing value = default(T); will not work for primitive types like int. That's also why I named it GetDefault instead of SetToDefault this time.
var myWhatever = 3.4;
myWhatever = myWhatever.GetDefault();
Inside the for loop put the following statement:
var default_val = Activator.CreateInstance(element.GetType());
This is how you set to default value
and here is a complete working example of your program
class Program
{
static void Main(string[] args)
{
var my_list = new List<int>() { 1, 2, 3 };
var list2 = set_to_default<List<int>>(my_list);
foreach (var elem in list2)
{
Console.WriteLine(elem);
}
Console.ReadKey();
}
public static T set_to_default<T>(T the_obj)
{
IEnumerable the_enumerable = the_obj as IEnumerable;
if (the_enumerable != null)
{
Type type = the_enumerable.GetType().GetGenericArguments()[0];
Type listType = typeof(List<>).MakeGenericType(new[] { type });
IList list = (IList)Activator.CreateInstance(listType);
var looper = the_enumerable.GetEnumerator();
while (looper.MoveNext())
{
var current_obj = looper.Current;
current_obj = Activator.CreateInstance(current_obj.GetType());
list.Add(current_obj);
}
return (T)list;
}
else
{
return default(T);
}
}
}
I suggest to use lists instead of enumerables because the last ones are immutable. That is once you create them you cannot edit them.
Final thing....if you want to support other types of IEnumerable the are not IList you may use the C# 'is' keyword to figure it out. In this case you need to know the underlying type of your enumerable at run-time. You may do that using the C# 'is' keyword
if (the_enumerable is IList)
{
editableType = typeof(List<>).MakeGenericType(new[] { type });
}
else if(the_enumerable is ICollection)
{
......
}

C# Lists reference with two?

I need 2 lists which are separate and one list containing the items of these two lists.
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
List<int> list3 = list1 & list2
When I add some integers in list1, I would like them to appear in list3 as well.
I want the same behavior when a new item is added into list2.
A reference of more than one lists.
Is this possible?
No, you can't do that with List<T> directly. However, you could declare:
IEnumerable<int> union = list1.Union(list2);
Now that will be lazily evaluated - every time you iterate over union, it will return every integer which is in either list1 or list2 (or both). It will only return any integer once.
If you want the equivalent but with concatenation, you can use
IEnumerable<int> concatenation = list1.Concat(list2);
Again, that will be lazily evaluated.
As noted in comments, this doesn't expose all the operations that List<T> does, but if you only need to read from the "combined integers" (and do so iteratively rather than in some random access fashion) then it may be all you need.
Is it possible?
Not with List since it's a static data structure - however you could use a query that is the concatenation of the two lists. Then whenever you enumerate the query it will show the current contents:
List<int> list1 = new List<int>();
List<int> list2 = new List<int>();
IEnumerable<int> list3 = list1.Concat(list2);
But as soon as you materialize the query into a data structure (by calling ToList, ToArray, etc.) the contents are static and will not update if one of the underlying lists updates.
No. You can create your own custom type that exposes methods similar to what a List<T> does (an indexer, Add, Remove methods, etc.), possibly even implementing IList<T>, but it wouldn't be a List<T>.
public class CompositeList<T> : IList<T>
{
private IList<IList<T>> lists;
public CompositeList(IList<IList<T>> lists)
{
this.lists = lists;
}
public CompositeList(params IList<T>[] lists)
{
this.lists = lists;
}
public int IndexOf(T item)
{
int globalIndex = 0;
foreach (var list in lists)
{
var localIndex = list.IndexOf(item);
if (localIndex >= 0)
return globalIndex + localIndex;
else
globalIndex += list.Count;
}
return -1;
}
public void Insert(int index, T item)
{
//note that there is an ambiguity over where items should be inserted
//when they are on the border of a set of lists.
foreach (var list in lists)
{
//use greater than or equal instead of just greater than to have the inserted item
//go in the later of the two lists in ambiguous situations,
//rather than the former.
if (index > list.Count)
index -= list.Count;
else
{
list.Insert(index, item);
return;
}
}
//TODO deal with having no lists in `lists`
//TODO deal with having only empty lists in `lists`
throw new IndexOutOfRangeException();
}
public void RemoveAt(int index)
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
list.RemoveAt(index);
}
throw new IndexOutOfRangeException();
}
public T this[int index]
{
get
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
return list[index];
}
throw new IndexOutOfRangeException();
}
set
{
foreach (var list in lists)
{
if (index > lists.Count)
index -= list.Count;
else
list[index] = value;
}
throw new IndexOutOfRangeException();
}
}
public void Add(T item)
{
if (!lists.Any())
lists.Add(new List<T>());
lists[lists.Count - 1].Add(item);
}
public void Clear()
{
foreach (var list in lists)
list.Clear();
}
public bool Contains(T item)
{
return lists.Any(list => list.Contains(item));
}
public void CopyTo(T[] array, int arrayIndex)
{
if (array.Length - arrayIndex - Count < 0)
throw new ArgumentException("The array is not large enough.");
int iterations = Math.Min(array.Length, Count);
for (int i = arrayIndex; i < iterations; i++)
array[i] = this[i];
}
public int Count
{
get { return lists.Sum(list => list.Count); }
}
public bool IsReadOnly
{
get { return false; }
}
public bool Remove(T item)
{
foreach (var list in lists)
{
if (list.Remove(item))
return true;
}
return false;
}
public IEnumerator<T> GetEnumerator()
{
return lists.SelectMany(x => x).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

How to Enumerate a generic List<T> without know the type

I am passing a generic list to a function , i want to enumerate the objects in the list. If i able to enumerate items in list i will use reflection to the rest.
var Items= new List<String>(){"s1","s2"};
Enumerate(Items);
void Enumerate(object items)
{
//i know the type so i can cast and enumerate
foreach(var item in (List<String>) items)
{
}
// i don't know the type of object in the list
//Following won't work , can't cast to List<object>
foreach (var item in (List<object>) items)
{
}
}
I'm not sure what your end-game goals are. If you expect a list, specifically a generic list, why not go with a generic method, as in:
void Enumerate<T>(List<T> items)
{
for(var item in items)
{
//...
}
}
This is described in more detail at http://msdn.microsoft.com/en-us/library/twcad0zb(VS.80).aspx.
I just want to add that the above method, on its own, defeats the purpose of a simple for in loop. Again, I don't know what Enumerate is meant to do above and beyond iterating over items.
You can make your function generic
public void Enum<T>(List<T> list)
{
foreach (T t in list)
{
}
}
The version of your function that works is:
var Items= new List<String>(){"s1","s2"};
Enumerate(Items);
void Enumerate<T>(List<T> items)
{
if (typeof(T) == typeof(string))
{
//i know the type so i can cast and enumerate
foreach(string item in (List<String>) items)
{
}
}
else
{
// i don't know the type of object in the list
//Following won't work , can't cast to List<object>
foreach (T item in items)
{
}
}
}
But this can be written better as:
void Enumerate<T>(List<T> items)
{
foreach (T item in items)
{
if (typeof(T) == typeof(string))
{ /* Do something */ }
else
{ /* Do something else */ }
}
}
I have a static class where I have some utils functions like an string enumerator from a list:
public static string EnumerateStrings<T>(this List<T> items, string separator = "; ")
{
var result = "";
if(typeof(T) == typeof(string) && items.SafeAny())
{
items.ForEach(str => {
try
{
if (!String.IsNullOrEmpty(str as string))
{
if (!String.IsNullOrEmpty(result))
result += separator;
result += str;
}
}
catch { }
});
}
return result;
}
And with this function you only need to use like this:
string myCarsEnumeration = Cars.Select(ob => ob.Name).ToList().EnumerateStrings();
//output-> Porsche; Lexus; Peugeot
//or
string myCarsEnumeration2 = Cars.Select(ob => ob.Name).ToList().EnumerateStrings(", ");
//output-> Porsche, Lexus, Peugeot
You can adapt to work with more object types.
The code of SafeAny():
public static bool SafeAny<T>(this IEnumerable<T> list, Func<T, bool> predicate)
{
return list != null && list.Any(predicate);
}

foreach with index [duplicate]

This question already has answers here:
How do you get the index of the current iteration of a foreach loop?
(35 answers)
Closed 9 years ago.
Is there a C# equivalent of Python's enumerate() and Ruby's each_with_index?
I keep this extension method around for this:
public static void Each<T>(this IEnumerable<T> ie, Action<T, int> action)
{
var i = 0;
foreach (var e in ie) action(e, i++);
}
And use it like so:
var strings = new List<string>();
strings.Each((str, n) =>
{
// hooray
});
Or to allow for break-like behaviour:
public static bool Each<T>(this IEnumerable<T> ie, Func<T, int, bool> action)
{
int i = 0;
foreach (T e in ie) if (!action(e, i++)) return false;
return true;
}
var strings = new List<string>() { "a", "b", "c" };
bool iteratedAll = strings.Each ((str, n)) =>
{
if (str == "b") return false;
return true;
});
You can do the following
foreach (var it in someCollection.Select((x, i) => new { Value = x, Index = i }) )
{
if (it.Index > SomeNumber) //
}
This will create an anonymous type value for every entry in the collection. It will have two properties
Value: with the original value in the collection
Index: with the index within the collection
The C# foreach doesn't have a built in index. You'll need to add an integer outside the foreach loop and increment it each time.
int i = -1;
foreach (Widget w in widgets)
{
i++;
// do something
}
Alternatively, you could use a standard for loop as follows:
for (int i = 0; i < widgets.Length; i++)
{
w = widgets[i];
// do something
}
I like being able to use foreach, so I made an extension method and a structure:
public struct EnumeratedInstance<T>
{
public long cnt;
public T item;
}
public static IEnumerable<EnumeratedInstance<T>> Enumerate<T>(this IEnumerable<T> collection)
{
long counter = 0;
foreach (var item in collection)
{
yield return new EnumeratedInstance<T>
{
cnt = counter,
item = item
};
counter++;
}
}
and an example use:
foreach (var ii in new string[] { "a", "b", "c" }.Enumerate())
{
Console.WriteLine(ii.item + ii.cnt);
}
One nice thing is that if you are used to the Python syntax, you can still use it:
foreach (var ii in Enumerate(new string[] { "a", "b", "c" }))
Aside from the LINQ answers already given, I have a "SmartEnumerable" class which allows you to get the index and the "first/last"-ness. It's a bit ugly in terms of syntax, but you may find it useful.
We can probably improve the type inference using a static method in a nongeneric type, and implicit typing will help too.
My solution involves a simple Pair class I created for general utility, and which is operationally essentially the same as the framework class KeyValuePair. Then I created a couple extension functions for IEnumerable called Ordinate (from the set theory term "ordinal").
These functions will return for each item a Pair object containing the index, and the item itself.
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs)
{
return lhs.Ordinate(0);
}
public static IEnumerable<Pair<Int32, X>> Ordinate<X>(this IEnumerable<X> lhs, Int32 initial)
{
Int32 index = initial - 1;
return lhs.Select(x => new Pair<Int32, X>(++index, x));
}
No, there is not.
As other people have shown, there are ways to simulate Ruby's behavior. But it is possible to have a type that implements IEnumerable that does not expose an index.
This is your collection
var values = new[] {6, 2, 8, 45, 9, 3, 0};
Make a range of indexes for this collection
var indexes = Enumerable.Range(0, values.Length).ToList();
Use the range to iterate with index
indexes.ForEach(i => values[i] += i);
indexes.ForEach(i => Console.Write("[{0}] = {1}", i, values[i]));
I just figured out interesting solution:
public class DepthAware<T> : IEnumerable<T>
{
private readonly IEnumerable<T> source;
public DepthAware(IEnumerable<T> source)
{
this.source = source;
this.Depth = 0;
}
public int Depth { get; private set; }
private IEnumerable<T> GetItems()
{
foreach (var item in source)
{
yield return item;
++this.Depth;
}
}
public IEnumerator<T> GetEnumerator()
{
return GetItems().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
// Generic type leverage and extension invoking
public static class DepthAware
{
public static DepthAware<T> AsDepthAware<T>(this IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
public static DepthAware<T> New<T>(IEnumerable<T> source)
{
return new DepthAware<T>(source);
}
}
Usage:
var chars = new[] {'a', 'b', 'c', 'd', 'e', 'f', 'g'}.AsDepthAware();
foreach (var item in chars)
{
Console.WriteLine("Char: {0}, depth: {1}", item, chars.Depth);
}
It depends on the class you are using.
Dictionary<(Of <(TKey, TValue>)>) Class For Example Support This
The Dictionary<(Of <(TKey, TValue>)>) generic class provides a mapping from a set of keys to a set of values.
For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair<(Of <(TKey, TValue>)>) structure representing a value and its key. The order in which the items are returned is undefined.
foreach (KeyValuePair kvp in myDictionary) {...}

Categories

Resources