Indexer in Generic Array - c#

Hi
i have created a Generic Array that works fine for Int,String, Float or even my Own type named Customers.
Generic Array has functions Add(), Sort(), ShowAll() thats working fine for Int, String, and even Customer Type
except when i try to showAll() method for CustomerType that shows all the values that i have added through ADD() method.
output is something like
GenericArray.Customer
not the values where as i wanted to have the values .
i have solved it through
public class GArray<T> where T : Customer
but now i cant create Generic Array of type Int,Float .
here is the ADD and ShowAll method of Class
public void Add(T temp)
{
if (index >= values.Length)
{
T[] tempArray = new T[values.Length + 1];
Array.Copy(values, tempArray, values.Length);
values = tempArray;
}
values[index] = temp;
index++;
}
public void ShowAll()
{
for (int i = 0; i < values.Length; i++)
{
Console.WriteLine(values[i]);
}
}
the values m adding
static void Main(string[] args)
{
GArray<Customer> customers = new GArray<Customer>(3);
customers.Add(new Customer(101, "xyz"));
customers.Add(new Customer(59, "abc"));
customers.ShowAll();
}
i have talked with my frnd and he said that i have to create indexer my self . can some one help me how can i create indexer in this case that works fine for customerType or any Type.

I think,If I understand the question (output is something like GenericArray.Customer, not the values where as i wanted to have the values) you should add in Customer definition:
public override string ToString()
{
// return something you want to show to identify your customer
// e.g. return Name;
return ...
}
I explain: when you use Console.WriteLine(values[i]) you tell C# to write to console Customer object... and it writes out then name of the class, as it's the default behaviour.
Defining in Customer class the default string to be converted to makes what you please...

public T this[int index]
{
get {return values[index]; }
}

I think your problem is that you have not overridden ToString in your customer class. Do that -- it will define how the objects should be displayed in the console.

Your actual problem aside for a moment, I would like to mention that there is no place for a ShowAll method in an array implementation. Why should an array be tied to a console application? Wouldn't you want to reuse it for a Windows Forms application oneday without the need to rewrite it?
Next, .NET already has a List<T> which does dynamic allocation as necessary. If you do want to write it again yourself, at least allocate the array in bigger steps (n*2 each time).
To remove the ShowAll method from the array (where it doesn't belong), you should consider taking one of the following approaches:
a) Create an extension method which works for any IEnumerable<T> (a List, Array, Collection, whatever):
public static class EnumExt
{
public static void ShowAll<T>(this IEnumerable<T> list)
{
foreach (T item in list)
Console.WriteLine(item);
}
}
Usage:
int[] array = new int[] { 1,2,3};
array.ShowAll();
b) Or, be even more abstract and create a ForEach extension method where you will pass an arbitrary delegate to perform actual work:
public static class EnumExt
{
public static void ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T item in list)
action(item);
}
}
Usage:
int[] array = new int[] { 1,2,3};
// now you are reusing the iterator
// for any action you want to execute
array.ForEach(Console.WriteLine);
// or
array.ForEach(item => Console.WriteLine("My item is: " + item));

Related

How to loop thru a Generic Class / List

Hi I'm learning Generics thru MSDN here
and I want to do a foreach loop to display data in a console.writeline.
I tried to do the foreach loop as below but it's not working.
// Declare the generic class.
public class GenericList<T>
{
public void Add(T input) { }
}
class TestGenericList
{
private class ExampleClass { }
static void Main()
{
// Declare a list of type int.
GenericList<int> list1 = new GenericList<int>();
list1.Add(150);
// Declare a list of type string.
GenericList<string> list2 = new GenericList<string>();
list2.Add("Toyota");
// Declare a list of type ExampleClass.
GenericList<ExampleClass> list3 = new GenericList<ExampleClass>();
list3.Add(new ExampleClass());
}
}
foreach (GenericList<T> item in list2.ToString().ToList())
{
Console.WriteLine(item); // NOT WORKING !!!!
}
Firstly, by calling the method ToString() on list2, you will get the name of type of your object, because you didn't create your own implementation of method ToString(). So, you are trying to enumerate through letters of string "AppName.GenericList". Unfortunately, letters are of type 'char' and not GenericList.
Secondly, there is no backend behind method Add - items you are 'adding' to your list, in reality aren't added anywhere. Method public void Add(T input) { } does nothing (you should fill the brackets). GenericList at this stage stores no data.
Thirdly, you can't enumerate through your GenericList, because you didn't implement the method GetEnumerator. Only then you will be able to use keyword foreach on objects of your type.
Many of this issues will be solved by the end of the tutorial from link that you provided.

How to create a List<long> from a long variable?

how can i convert a long variable into the list?
Code:
long taskId = long.Parse(LocalWorkListVM.ActiveTask.TaskId, CultureInfo.InvariantCulture);
I need to convert it into a List<long> because one of our method expect a list to pass.
So you need a List<long> but you only have a single variable. That's easy, you can use the collection initializer syntax:
List<long> longs = new List<long>{ taskId };
or more verbose with List.Add:
List<long> longs = new List<long>();
longs.Add( taskId );
Try this:
List<long> somelist = new List<long>{long.Parse(LocalWorkListVM.ActiveTask.TaskId, CultureInfo.InvariantCulture)};
This will create a new List and initialise it with the parsed value.
Does it really need to be a List? If there is a way to modify that method to accept an IEnumerable things would get much easier and cleaner (or if IEnumerable is not enough, maybe consider IList).
So considering this, you have a bunch of options.
You can use the Enumerable class' static method Repeat:
Enumerable.Repeat(taskId, 1);
You can write your own extension method:
static class IEnumerableExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this T item)
{
yield return item;
}
}
// and use it as:
taskId.ToEnumerable()
Of course this extension method can be modified to return a List or IList or whatever your exact needs are.
Also, you might create a new overload of the function, which expects a single long instead of the List, somewhere along the lines of this:
public void MyMethod(List<long> list)
{
// Do something
}
public void MyMethod(long item)
{
MyMethod(new List<long>{ item });
}
And finally, there is a nice keyword called params:
public void MyMethod(params long[] items)
{
// call to the previously mentioned extension method
MyMethod(items.ToEnumerable());
}
public void MyMethod(IEnumerable<long> items)
{
// Do stuff
}
This solution has the advantage to work with a single long parameter, comma separated long parameters or with an IEnumerable<long>.

Distinct Function C#

Edit:
The original question was based on this code that I saw below elsewhere:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// List with duplicate elements.
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(3);
list.Add(4);
list.Add(4);
list.Add(4);
foreach (int value in list)
{
Console.WriteLine("Before: {0}", value);
}
// Get distinct elements and convert into a list again.
List<int> distinct = list.Distinct().ToList();
foreach (int value in distinct)
{
Console.WriteLine("After: {0}", value);
}
}
}
I apologize for my question was not specific enough.
Distinct is similar to distinct in a SQL Query .
Ex: var distinctElements = duplicatedElements.Distinct();
The above code filters out duplicate entries and returns an IEnumerable<T> of distinct elements. The original duplicatedElements is left intact though
Distinct does not do this, as Eric says. Instead, it feeds you distinct elements of a container in an IEnumerable<T>. The exact implementation of Distinct actually varies on the container.
Consider the following code snippet:
public static class StaticyGoodness
{
public static void Main()
{
var someAs = new List<A>();
var someBs = new List<B>(); // get it?
DoTheThings(someAs);
// Doing things the regular way
DoTheThings(someBs);
// Doing things the SPECIALIZED way
DoTheThings(someBs.OrderBy(b => b.Stuff));
// Doing things the REALLY SPECIALIZED way
}
private static void DoTheThings<T>(this IEnumerable<T> source)
{
Console.WriteLine("Doing things the regular way");
}
private static void DoTheThings(this IEnumerable<B> source)
{
Console.WriteLine("Doing things the SPECIALIZED way");
}
private static void DoTheThings(this IOrderedEnumerable<B> source)
{
Console.WriteLine("Doing things the REALLY SPECIALIZED way");
}
}
public class A { }
public class B : A { public int Stuff { get; set; } }
Depending on what exactly you give to the DoTheThings function, a different overload gets bound at compile time. I found this surprising. I thought the runtime would choose a better candidate, if there was one, at runtime based on the thing's actual type instead of its declared type.
For example, if we extract the OrderBy expression to a local variable, declaring it as IEnumerable<B> instead of IOrderedEnumerable<B> (e.g. we are returning from a repository method but don't want to expose the implementation detail of its having been sorted), the REALLY SPECIALIZED call would not be made.
IEnumerable<B> plainEnumerable = someBs.OrderBy(b => b.Stuff);
DoTheThings(plainEnumerable);
// Doing things the SPECIALIZED way :( (ed.)

C# Generic overloading of List<T> : How would this be done?

The StringBuilder class allows you, in what I consider to be a very intuitive way, to chain method calls to .Append(), .AppendFormat() and some others like so:
StringBuilder sb = new StringBuilder();
sb.Append("first string")
.Append("second string);
The List class' .Add() method, on the other hand, returns void - so chaining calls doesn't work. This, in my opinion and the immortal words of Jayne Cobb "just don' make no kinda sense".
I admit that my understanding of Generics is very basic, but I would like to overload the .Add() method (and others) so that they return the original object, and allow chaining. Any and all assistance will be rewarded with further Firefly quotes.
If you want to keep the same name for the Add method, you could hide the method from the base class:
public class MyList<T> : List<T>
{
public new MyList<T> Add(T item)
{
base.Add(item);
return this;
}
}
However, this will only work if you're manipulating the list with a variable explicitly typed as MyList<T> (i.e. it won't work if your variable is declared as IList<T> for instance). So I think the solutions involving an extension method are better, even if that means changing the name of the method.
Although others have already posted solutions with extension methods, here's another one, that has the advantage of conserving the actual type of the collection:
public static class ExtensionMethods
{
public static TCollection Append<TCollection, TItem>(this TCollection collection, TItem item)
where TCollection : ICollection<TItem>
{
collection.Add(item);
return collection;
}
}
Use it like that:
var list = new List<string>();
list.Append("Hello").Append("World");
use can create extension method
public static class ListExtensions
{
public static List<T> AddItem<T>(this List<T> self, T item)
{
self.Add(item);
return self;
}
}
var l = new List<int>();
l.AddItem(1).AddItem(2);
EDIT
we can also make this method generic over collection parameter
public static class ListExtensions
{
public static TC AddItem<TC, T>(this TC self, T item)
where TC : ICollection<T>
{
self.Add(item);
return self;
}
}
var c1 = new Collection<int>();
c1.AddItem(1).AddItem(2);
var c2 = new List<int>();
c2.AddItem(10).AddItem(20);
EDIT 2:
Maybe someone will find this trick useful, it is possible to utilize nested object initializer and collection initializer for setting properties and adding values into existing instances.
using System;
using System.Collections.Generic;
using System.Linq;
struct I<T>
{
public readonly T V;
public I(T v)
{
V = v;
}
}
class Obj
{
public int A { get; set; }
public string B { get; set; }
public override string ToString()
{
return string.Format("A={0}, B={1}", A, B);
}
}
class Program
{
static void Main()
{
var list = new List<int> { 100 };
new I<List<int>>(list)
{
V = { 1, 2, 3, 4, 5, 6 }
};
Console.WriteLine(string.Join(" ", list.Select(x => x.ToString()).ToArray())); // 100 1 2 3 4 5 6
var obj = new Obj { A = 10, B = "!!!" };
Console.WriteLine(obj); // A=10, B=!!!
new I<Obj>(obj)
{
V = { B = "Changed!" }
};
Console.WriteLine(obj); // A=10, B=Changed!
}
}
public static IList<T> Anything-not-Add*<T>(this IList<T> list, T item)
{
list.Add(item);
return list;
}
* AddItem, Append, AppendList, etc. (see comments below)
The same idea came to my mind like other guys' too, independently:
public static TList Anything<TList, TItem>(this TList list, TItem item)
where TList : IList<TItem>
{
list.Add(item);
return list;
}
And Thomas is right: as far as IList<T> inherits ICollection<T> you should use ICollection.
Have an extension method off:
public static List<T> Append(this List<T> list, T item)
{
list.Add(item);
return self;
}
Note that we have to create it with a new name, as if an instance member matches the signature (the 'Add' you are already complaining about) then the extension method won't be called.
In all though, I'd recommend against this. While I like chaining myself, it's being rare in C# libraries means it's not as idiomatic as it is in other languages where it's more common (no technical reason for this, though some differences in how properties work encourages it a bit more in some other languages, just the way things are in terms of what is common). Because of this, the constructs it enables aren't as familiar in C# as elsewhere, and your code is more likely to be misread by another dev.
You could use an extension method with a different name:
public static T Put<T, U>(this T collection, U item) where T : ICollection<U> {
collection.Add(item);
return collection;
}
To create code like this:
var list = new List<int>();
list.Put(1).Put(2).Put(3);
To retain the name Add, however, you can have a method like this:
public static T Add<T, U>(this T collection, Func<U> itemProducer)
where T : ICollection<U> {
collection.Add(itemProducer());
return collection;
}
And create code like this:
list.Add(()=>1).Add(()=>2).Add(()=>3);
It doesn't look that good though.
Maybe if we change the type we can have a better syntax.
Given this class:
public class ListBuilder<T> {
IList<T> _list;
public ListBuilder(IList<T> list) {
_list = list;
}
public ListBuilder<T> Add(T item) {
_list.Add(item);
return this;
}
}
You can have this method:
public static ListBuilder<T> Edit<T>(this IList<T> list) {
return new ListBuilder<T>(list);
}
And use code like this:
list.Edit().Add(1).Add(2).Add(3);
I'm sure you won't appreciate this answer but there's a very good reason that List<>.Add() works this way. It is very fast, it needs to be to be competitive with an array and because it is such a low-level method. It is however just a hair too big to get inlined by the JIT optimizer. It cannot optimize the return statement you'd need to return the list reference.
Writing lst.Add(obj) in your code is for free, the lst reference is available in a CPU register.
A version of Add() that returns the reference makes the code almost 5% slower. It's a lot worse for the proposed extension method, there an entire extra stack frame involved.
I like the extension approach that others have mentioned as that seems to answer the question well (although you would have to give it a different method signature than the existing Add()). Also, it does seem like there's some inconsistency about object returns on calls like this (I thought it was a mutability issue, but the stringbuilder is mutable isn't it?), so you raise an interesting question.
I'm curious, though, if the AddRange method would not work as an out-of-the-box solution? Is there a particular reason you want to chain the commands instead of passing everything in as a an array?
Would do something like this not accomplish what you need?
List<string> list = new List<string>();
list.AddRange(new string[]{
"first string",
"second string",
});

enumerate through all IEnumerables

I need to send different IEnumerables to an Printer object.
This printer object will then do something to them, inside a foreach loop.
class Printer
{
public Printer(IEnumerable list)
{
foreach (var enumerable in list)
{
//DO STUFF
}
}
}
This lets me send any enumerable, such as an List<T> to the printer object.
such as
var list = new List<string> {"myList"};
new Printer(list); //mylist
This works fine.
BUT if I send a Dictionary<T, T> such as:
var dictionary = new Dictionary<int, string> {{1, "mydict"}};
new Printer(dictionary); //[1, mydict]
It'll have a key and a value. What I would want though, would be separate access to the Value property inside the foreach loop. All I DO have access to is the enumerable object, which has no properties I can use.
Now what if the datatype T is an object containing several properties (this goes for both examples). How would I be able to use these properties in my foreach loop?
Do I honestly have to create an overload of the constructor, foreach possible datatype I might send down to it?
Also, all I need to do in the foreach is not dependable to any datatypes - as it won't manipulate everything. I do need ACCESS to all the properties though.
Also, this is just example code, not actually the production-code I use in my application.
Can you change the code of the Printer class? If it accepted something like an IEnumerable<IPrintable> instead of just an IEnumerable it would be easier. With an interface like this:
interface IPrintable
{
void Print();
}
Then all objects that would be sent to the Printer would need to implement that interface. Then you could do:
class Printer
{
public Printer(IEnumerable<IPrintable> list)
{
foreach (var enumerable in list)
{
enumerable.Print();
}
}
}
And if you have a dictionary of printable objects, something like:
var dict = new Dictionary<int,IPrintable>();
You could just pass the values to the function:
var printer = new Printer(dict.Values);
You could modify your method to accept a delegate that returns the data the print method needs. Something like this:
// You will not need this class, if you always want a single string result.
class PrinterData
{
public string Value { get; set; }
// More properties?
}
class Printer
{
public Printer<T>(IEnumerable<T> list, Func<T, PrinterData> func)
{
foreach (T item in list)
{
PrinterData data = func(item);
// Do something with the data.
}
}
}
Usage:
int[] ints = new int[] {1,2,3};
new Printer().Print(ints, x => new PrinterData() { Value = x.ToString() });
var dictionary = new Dictionary<int, string> {{1, "mydict"}};
new Printer().Print(dictionary, x => new PrinterData() { Value = x.Name + " = " + x.Value });
Per Erik Stendahl's answer is very similar.
You have to extract an enumerable with the values you want to pass before you call new Printer(). In the case of the dictionary this is simple: just use dict.Values. A more general case is:
var list = List<MyObject>()...
var printer = new Printer(list.Select(x => x.MyProperty));
If you want to treat different types differently, you probably should make different methods. If you want to treat them the same, you should accept a common interface, and only use the methods defined for the interface.
It would be possible to do
if (list is Dictionary<int, string>) {
// do special case
}
but I shudder at the thought.
You can even check generically:
class Printer<T>
{
public Printer<T>(IEnumerable list)
{
foreach (var enumerable in list)
{
if (list is Dictionary<T, T>) {
//DO STUFF
}
}
}
}
The problem is that a collection, though it is enumerable, can hold different types of objects, as you saw with the difference between the List and the Dictionary.
To get around this without coding for each object type, you'd have to only accept an enumerable collection of a certain type that you define, for example IEnumerable<IMyType>.
If you can't do anything at the callee, it's up to the caller to make sure it passes an IEnumerable that is "valid" for Printer, like passing dictionary.Values instead of dictionary in your example. However if the class is public and will be used by 3rd party users, you're better to add some generic constraint to your IEnumerable, as others stated.
Here is the result:
I used your guys help, so I guess I shouldn't vote my own as the answer.
class Printer
{
public Printer(IEnumerable<IPrintable> list) //Accepts any collection with an object that implements IPrintable interface
{
foreach (var enumerable in list) //iterate through list of objects
{
foreach (var printable in enumerable)//loops through properties in current object
{
//DO STUFF
}
}
}
}
interface IPrintable : IEnumerable { }
class SomeObject : IPrintable
{
public string Property1 { get; set; }
public string Property2 { get; set; }
public interface IEnumerable
{
IEnumerator GetEnumerator(); //Returns a Enumerator
}
public IEnumerator GetEnumerator()
{
yield return Property1;
yield return Property2;
}
}
I'd naturally need to implement custom GetEnumerator() foreach object - no problem though!

Categories

Resources