Home > OS >  C# - Tuple inside List<> Instantiation and Declaration
C# - Tuple inside List<> Instantiation and Declaration

Time:07-15

My goal is to create a List of pairs (of ONLY type double). For example: { {1.0,1.1}, {1.2,1.3}, {1.4,1.5}, {...}, {...} } where {1.0,1.1} is List[0], {1.2,1.3} is List[1], {1.4,1.5} is List[2], et cetera.

RATION ERROR

              Tuple<double,double> a1 = new Tuple<double,double>(1.0, 1.1);

              Tuple<double,double> a2 = new Tuple<double,double>(1.2, 1.3);

              Tuple<double,double> a3 = new Tuple<double,double>(1.4, 1.5);

            //List< Tuple<double,double> >  a4 = new List< Tuple<double, double> >(a1, a2, a3);      //ERROR

              List< Tuple<double,double> >  a5 = new List< Tuple<double, double> >{a1, a2, a3};  //COMPILES

              List< Tuple<double,double> >  a6 = new List< Tuple<double, double> >(){a1, a2, a3};    //COMPILES

            //List< Tuple<double,double> >  a7 = new List< Tuple<double, double> >{a1, a2, a3}();    //ERROR
  1. In a4, a5, a6, and a7, why are the () optional but the {} are not?
  2. In a4, why can I not use () for instantiating the List<>, considering the () is made for instantiation arguments?
  3. Does 2. have the same reasoning as the error when trying to instantiate a7?

I know that [] always indicates selecting an element in an array, hence why I didn't try that.

Also, I am aware of ValueTuple but I want compatibility with previous versions of C# and/or .NET (idk the difference) and Tuple is not significantly more amazing than ValueTuple.

CodePudding user response:

When you use { a1, a2, a3 } you're using the collection initializer. In this situation, you don't necessarily have to add () to call the parameterless constructor of the collection. That's why new List<int>() { 1 } would work just as well as new List<int> { 1 }.

A more complex example might be to specify the initial capacity (not number of items) of the list, and add fewer items: new List<int>(5) { 1, 2, 3 }. This would give us a list with 3 items in it, but with a capacity of 5 (so it doesn't need to internally resize its arrays until we try to add a 6th item).

As for why new List<int>(1, 2, 3) wouldn't work: there simply isn't a constructor that accepts items in this format.

Consider these two methods:

public static void Test1(int[] items)
{
}

public static void Test2(params int[] items)
{
}

We can call Test1 as Test1(new int[] { 1, 2, 3 }) but not as Test1(1, 2, 3). Because Test2 has the params keyword, we can call it both as Test2(new int[] { 1, 2, 3 }) and Test2(1, 2, 3). It's the params keyword that does the magic here.

Now, the following list constructors are available:

  • public List (); - this doesn't take any parameters, and is what we use when we write new List<int> { 1 } (implicit) or new List<int>() { 1 } (explicit).
  • public List (System.Collections.Generic.IEnumerable<T> collection); - this allows you to pass any object that implements IEnumerable<T>. This is why new List<int>(new int[] { 1, 2, 3 }) works. Arrays (int[]) implement IEnumerable<T>, as do lists, queues, dictionaries, and all sorts of other collection types.
  • public List (int capacity); - This just sets the capacity, and is what we use if we call new List<int>(5) { 1, 2, 3 };

There is no constructor that accepts params T[], so we simply can't construct a list like new List<int>(1, 2, 3);.

Documentation:

  • Related