Generics - Clarification Required - c#

When we declare (example) List<T> I can understand the declaration, but suppose I declare
IEnumerable<T<T1, T2>>
What did I actually declare?
Does it mean, IEnumerable<T> contains two generic types? (What is the way to use it?)
Can I have deep nested level like Person<T<T2<T3<P1,P2>>>>?
Simple example will really helpful.

If you have a class
public class Pair<T1, T2> { ... }
then you can declare a method
IEnumerable<Pair<int, string>> GetPairs();
i.e. a method that returns an enumerable of pairs where each pair consists of an int and a string.
Usage:
foreach (Pair<int, string> pair in GetPairs()) { ... }
You can also deeply nest these:
IEnumerable<Pair<int, Pair<string, string>>> GetPairs();
i.e. a method that returns an enumerable of pairs where each pair consists of an int and a pair of two strings.
This works with generics as well:
IEnumerable<Pair<T1, T2>> GetPairs<T1, T2>();
i.e. a method that returns an enumerable of pairs where each pair consists of a T1 and a T2.
But you cannot do this:
IEnumerable<T<T1, T2>> GetGenericPairs<T, T1, T2>();

Unless you've actually got a generic type called T, that won't work. You need a real type there, e.g.
IEnumerable<Dictionary<string, int>>
which is a sequence of Dictionary<string, int> references.
But yes, you can nest generics a lot - and it becomes pretty unreadable:
List<Dictionary<List<IEnumerable<string>>, Dictionary<int, int>>> aargh = null;

The above example will not compile. But you can embed Generic types within one another with something like this:
IEnumerable<IEnumerable<int>>
Which would be an enumerable of an enumerable of ints (which would act as a jagged 2 dimensional array).

(1) You declared an IEnumerable that enumerates objects of type T<T1, T2>. For example, Hashtable<Int, String>.
(2) Sure you can!

Related

What IEnumerable<IEnumerable<>> means?

Some methods in c# that i have seen , requires IEnumerable<IEnumerable<"some class">>. When method need IEnumerable<"some class"> as a parameter , i can pass a one-dimensional array or list . I thought by the same logic i can pass two-dimensional array as IEnumerable<IEnumerable<"some class">> , but my compiler says it is not the same. What data types i can pass to such methods, for example?
For example IEnumerable<IEnumerable<int>> is an enumeration of an enumeration of integers.
https://www.codingame.com/playgrounds/213/using-c-linq---a-practical-overview/ienumerablet
https://learn.microsoft.com/dotnet/api/system.collections.generic.ienumerable-1
It means that each element of the root list is a list of int.
If we write:
IEnumerable<IEnumerable<int>> listOfLists = GetItems();
We can parse items like that:
foreach ( var list in listOfLists )
{
Console.WriteLine("Values");
foreach ( var value in list )
Console.WriteLine(" " + value);
}
In fact if we declare:
var items = new List<List<int>>();
This is a IEnumerable<IEnumerable<int>> here.
It is like an array of arrays of int:
var items = int[][];
Here it is not a multidimentionnal array but a jagged array:
https://learn.microsoft.com/dotnet/csharp/programming-guide/arrays/jagged-arrays
https://www.tutorialsteacher.com/csharp/csharp-jagged-array
https://www.c-sharpcorner.com/UploadFile/puranindia/jagged-arrays-in-C-Sharp-net
IEnumerable is just an interface, which is implemented by a lot classes/types, two of which the List and Array (you can find the list here).
So, as as example, when the compiler tells you must pass a IEnumerable<"some class"> parameter it can be, for instance a List (depending if the "some class" refers to a string... if it refers to a class Car created by you then you must pass a List...) or string[] (which is an array of strings, which also implements this interface).
If you have to pass a IEnumerable<IEnumerable<"some class">> that means you have to have to layers of objects which implement the IEnumerable interface. You can have things like:
List<List>
string[][]
And others...
Long story short, it’s an interface that allows you to do a foreach loop on certain objects.

Best way to compare two generic values?

I'm writing a small class which I'm gonna move around when needed like a dll, and it's gonna have different sorting algorithms in it. I want the functions to work with any lists, of any types, including objects. So it's basically like this:
class TemplateSortings<T>
{
List<T> GNRList;
static void SortBubble<T>()
{
//Do stuff with GNRList, which can be a list of any values (nums, strings, objects)
}
}
Now the question I'm having troubles with is this - what is the best way to compare two generic values: overloading comparison operators or having the class inherit IComparable interface? What is better and why?
If you want it to work with any type, you probably shouldn't constrain T to types that implement IComparable, because not all types do.
A simple way to work around this is to let the caller decide how to compare the objects. You just need an extra parameter:
static void SortBubble(Func<T, T, int> comparator)
{
...
}
You can call comparator with 2 arguments and it will give you a negative value, 0, or a positive value indicating that the first parameter is less than, equal to, or greater than the second parameter.
As an example, you can call SortBubble with ints like this:
var sorting = new TemplateSortings<int>();
// populate the list...
sorting.SortBubble((x, y) => x.CompareTo(y)) // pass a lambda
EDIT:
If you don't want an extra parameter and want to check the type inside the method, you can do something like this:
if (typeof(IComparable<T>).IsAssignableFrom(typeof(T))) {
// do your sorting
// you need to cast values of type "T" to "Comparable<T>" like this
// var castedValue = (IComparable<T>)tValue;
} else {
throw ...
}
You could generalize your code so it can work with any potentially valid type T:
public static IEnumerable<T> BubbleSort(
this IEnumerable<T> source,
IComparer<T> comparer == null)
{
var currentComparer = comparer ?? Comparer<T>.Default;
//bubble sort with currentComparator
}
Now, you can sort any T whatsoever, if:
T implements IComparable<T>
T implements legacy IComparable
You hand down a Comparator that knows how to compare Ts
It will fail on any other scenario the moment you attempt to perform the first comparison.

Nested Interfaces: Cast IDictionary<TKey, IList<TValue>> to IDictionary<TKey, IEnumerable<TValue>>?

I would think it's fairly straightforward to cast an IDictionary<TKey, IList<TValue>> object to an IDictionary<TKey, IEnumerable<TValue>>, but
var val = (IDictionary<TKey, IEnumerable<TValue>>)Value;
throws a System.InvalidCastException, and
var val = Value as IDictionary<TKey, IEnumerable<TValue>>;
makes val null. What is the proper way to cast this?
I would think it's fairly straightforward to cast an IDictionary<TKey, IList<TValue>> object to an IDictionary<TKey, IEnumerable<TValue>>
Absolutely not. It wouldn't be type-safe. Here's an example of why not:
// This is fine...
IDictionary<string, IList<int>> dictionary = new Dictionary<string, IList<int>>();
// Suppose this were valid...
IDictionary<string, IEnumerable<int>> badDictionary = dictionary;
// LinkedList<T> doesn't implement IList<T>
badDictionary["foo"] = new LinkedList<int>();
// What should happen now?
IList<int> bang = dictionary["foo"];
As you can see, that's going to cause problems - we'd be trying to get a LinkedList<int> out when we expect all the values to implement IList<int>. The point of generics is to be type-safe - so which line would you expect to fail? The first, third and fourth lines look pretty clearly valid to me - so the second one is the only one which can fail to compile, and it does...
Now in some cases, it can be done safely. For example, you can convert (in C# 4) from IEnumerable<string> to IEnumerable<object> because IEnumerable<T> only uses T in "output" positions.
See MSDN for more details.
EDIT: Just to clarify - it's easy to create a new dictionary with a copy of the existing key/value pairs, e.g. using link:
var copy = original.ToDictionary<TKey, IEnumerable<TValue>>(pair => pair.Key,
pair => pair.Value);
You just need to be aware that you now have two separate dictionaries.
This may or may not help you, but I thought I'd throw it out as a supplement to Jon's answer.
If all you need is the dictionary's values, without reference to their keys, you can do this:
IDictionary<TKey, IList<TValue>> dictionary = Whatever();
var values = (IEnumerable<IEnumerable<TValue>>)dictionary.Values;
For this to work, you must be using C# 4.0 or later, and TValue must be constrained to be a reference type. Here's the code, slightly refactored, and with comments to explain:
IDictionary<TKey, IList<TValue>> dictionary = Whatever();
//Values returns an ICollection<IList<TValue>>
ICollection<IList<TValue>> temp1 = dictionary.Values;
//ICollection<T> inherits from IEnumerable<T>
IEnumerable<IList<TValue>> temp2 = temp1;
//IEnumerable<T> is covariant
//There is an implicit reference conversion between IList<T> and IEnumerable<T>
//So there is an implicit reference conversion between IEnumerable<IList<T>>
//and IEnumerable<IEnumerable<T>>
IEnumerable<IEnumerable<TValue>> values = temp2;

Sorted Dictionary - C#

I'm trying to figure out how to create a sorted dictionary where the key is sorted in a non-alphabetical manner. Is there a way I can define the way I want it to sort?
For example, the keys might be in order like the following:
AAA1X
AAB1Y
AAC1Y
AAA2X
AAB2Y
AAC2X
Although the first three letters are alphabetical, if I sort as is it will lump them in the wrong order (due to the number). Also note, that there is either a X or Y at the end. In the code, there will only ever be an X or a Y.
Even if I can write an enumeration for the ordering of all possible combinations I'd be willing to do that as well, but I'm not sure how I can use the sorted dictionary and an enumeration...
I know this is a bit vague, but any help would be much appreciated!
Cheers!
One of the constructors for SortedDictionary<TKey, TValue> takes an IComparer<TKey>, where you can specify a custom comparer class that the dictionary will use for sorting.
public class CustomComparer : IComparer<string>
{
public int Compare(string x, string y)
{
// do your own comparison however you like; return a negative value
// to indicate that x < y, a positive value to indicate that x > y,
// or 0 to indicate that they are equal.
}
}
...
SortedDictionary<string, object> dict =
new SortedDictionary<string, object>(new CustomComparer());
You can :
Create a class that encapsulates those keys and override the == operator, Object.Equals method and the Object.GetHashCode method. Also have the class implement the IComparable interface such that the rules for equality will automatically sort your keys the right way. Now you can simply place those keys in a SortedDictionary or SortedList and it will automatically sort the way you want.
OR
Implement an IComparer object that compares those strings the way you want, and specify the IComparer when constructing a SortedDictionaryor SortedList.

Will a future version of .NET support tuples in C#?

.Net 3.5 doesn't support tuples. Too bad, But not sure whether the future version of .net will support tuples or not?
I've just read this article from the MSDN Magazine: Building Tuple
Here are excerpts:
The upcoming 4.0 release of Microsoft
.NET Framework introduces a new type
called System.Tuple. System.Tuple is a
fixed-size collection of
heterogeneously typed data.
 
 
 
Like an array, a tuple has a fixed
size that can't be changed once it has
been created. Unlike an array, each
element in a tuple may be a different
type, and a tuple is able to guarantee
strong typing for each element.
 
There is already one example of a
tuple floating around the Microsoft
.NET Framework, in the
System.Collections.Generic namespace:
KeyValuePair. While KeyValuePair can be thought of as the same
as Tuple, since they are both
types that hold two things,
KeyValuePair feels different from
Tuple because it evokes a relationship
between the two values it stores (and
with good reason, as it supports the
Dictionary class).
Furthermore, tuples can be arbitrarily
sized, whereas KeyValuePair holds only
two things: a key and a value.
While some languages like F# have special syntax for tuples, you can use the new common tuple type from any language. Revisiting the first example, we can see that while useful, tuples can be overly verbose in languages without syntax for a tuple:
class Program {
static void Main(string[] args) {
Tuple<string, int> t = new Tuple<string, int>("Hello", 4);
PrintStringAndInt(t.Item1, t.Item2);
}
static void PrintStringAndInt(string s, int i) {
Console.WriteLine("{0} {1}", s, i);
}
}
Using the var keyword from C# 3.0, we can remove the type signature on the tuple variable, which allows for somewhat more readable code.
var t = new Tuple<string, int>("Hello", 4);
We've also added some factory methods to a static Tuple class which makes it easier to build tuples in a language that supports type inference, like C#.
var t = Tuple.Create("Hello", 4);
#region tuples
public class Tuple<T>
{
public Tuple(T first)
{
First = first;
}
public T First { get; set; }
}
public class Tuple<T, T2> : Tuple<T>
{
public Tuple(T first, T2 second)
: base(first)
{
Second = second;
}
public T2 Second { get; set; }
}
public class Tuple<T, T2, T3> : Tuple<T, T2>
{
public Tuple(T first, T2 second, T3 third)
: base(first, second)
{
Third = third;
}
public T3 Third { get; set; }
}
public class Tuple<T, T2, T3, T4> : Tuple<T, T2, T3>
{
public Tuple(T first, T2 second, T3 third, T4 fourth)
: base(first, second, third)
{
Fourth = fourth;
}
public T4 Fourth { get; set; }
}
#endregion
And to make declarations prettier:
public static class Tuple
{
//Allows Tuple.New(1, "2") instead of new Tuple<int, string>(1, "2")
public static Tuple<T1, T2> New<T1, T2>(T1 t1, T2 t2)
{
return new Tuple<T1, T2>(t1, t2);
}
//etc...
}
There is a proper (not quick) C# Tuple implementation in Lokad Shared Libraries (Open-source, of course) that includes following required features:
2-5 immutable tuple implementations
Proper DebuggerDisplayAttribute
Proper hashing and equality checks
Helpers for generating tuples from the provided parameters (generics are inferred by compiler) and extensions for collection-based operations.
production-tested.
Implementing Tuple classes or reusing F# classes within C# is only half the story - these give you the ability to create tuples with relative ease, but not really the syntactic sugar which makes them so nice to use in languages like F#.
For example in F# you can use pattern matching to extract both parts of a tuple within a let statment, eg
let (a, b) = someTupleFunc
Unfortunately to do the same using the F# classes from C# would be much less elegant:
Tuple<int,int> x = someTupleFunc();
int a = x.get_Item1();
int b = x.get_Item2();
Tuples represent a powerful method for returning multiple values from a function call without the need to litter your code with throwaway classes, or resorting to ugly ref or out parameters. However, in my opinion, without some syntactic sugar to make their creation and access more elegant, they are of limited use.
In my opinion, the anonymous types feature is not a tuple, but a very similar construct. The output of some LINQ Queries are collections of anonymous types, which behave like tuples.
Here is a statement, which creates a typed tuple :-) on the fly:
var p1 = new {a = "A", b = 3};
see: http://www.developer.com/net/csharp/article.php/3589916
C# 7 supports tuples natively:
var unnamedTuple = ("Peter", 29);
var namedTuple = (Name: "Peter", Age: 29);
(string Name, double Age) typedTuple = ("Peter", 29);
My open source .NET Sasa library has had tuples for years (along with plenty of other functionality, like full MIME parsing). I've been using it in production code for a good few years now.
C# supports simple tuples via generics quite easily (as per an earlier answer), and with "mumble typing" (one of many possible C# language enhancements) to improve type inference they could be very, very powerful.
For what it is worth, F# supports tuples natively, and having played with it, I'm not sure that (anonymous) tuples add much... what you gain in brevity you lose very quickly in code clarity.
For code within a single method, there are anonymous types; for code going outside of a method, I think I'll stick to simple named types. Of course, if a future C# makes it easier to make these immutable (while still easy to work with) I'll be happy.
Here's my set of tuples, they're autogenerated by a Python script, so I've perhaps gone a bit overboard:
Link to Subversion repository
You'll need a username/password, they're both guest
They are based on inheritance, but Tuple<Int32,String> will not compare equal to Tuple<Int32,String,Boolean> even if they happen to have the same values for the two first members.
They also implement GetHashCode and ToString and so forth, and lots of smallish helper methods.
Example of usage:
Tuple<Int32, String> t1 = new Tuple<Int32, String>(10, "a");
Tuple<Int32, String, Boolean> t2 = new Tuple<Int32, String, Boolean>(10, "a", true);
if (t1.Equals(t2))
Console.Out.WriteLine(t1 + " == " + t2);
else
Console.Out.WriteLine(t1 + " != " + t2);
Will output:
10, a != 10, a, True
If I remember my Computer Science classes correctly tuples are just data.
If you want grouped data - create classes that contain properties.
If you need something like the KeyValuePair then there it is.
I'd be surprised - C# is a strongly-typed language, whereas tuples are suited for more dynamically typed languages. C# has been drifting more dynamic as time goes on, but that's syntactic sugar, not a real shift in the underlying data types.
If you want two values in one instance, a KeyValuePair<> is a decent substitute, albeit clumsy. You can also make a struct or a class that'll do the same thing, and is expandable.
To make these useful in a hashtable or dictionary, you will likely want to provide overloads for GetHashCode and Equals.

Categories

Resources