Representing Typed N-tuples in C# - c#

List<struct {string, string, double} > L = new List<struct {string, string, double}>;
L.Add({"hi", "mom", 5.0});
What is the nicest way to get this functionality in C#? I want to define a strongly-typed tuple on the fly (for use in a local function), save a bunch of them in a list, do some processing and return a result, never to touch the list again.
I don't actually care about the strong typing, but a List of vars doesn't work. Do I want a list of objects? Is that the closest I can get?
Defining structs or classes for temporary data structures seems verbose and pedantic to me.

The best way to represent this in C# is to use the Tuple type
var l = new List<Tuple<string, string, double>>();
l.Add(Tuple.Create("hi", "mom", 42.0));
There's no explicit language support for tuples but as you can see the API isn't too wordy

var arr = new[] { Tuple.Create("hi","mom", 5.0) };
is the easiest; this is actually an array, but a list is easy enough too - perhaps .ToList() if you feel lazy.
Personally, in this scenario I'd use an anon-type:
var arr = new[] { new { Text = "hi", Name = "mom", Value = 5.0 } };
Very similar, except the member-names are more meaningful.

List<Tuple<string, string, double>> L = new List<Tuple<string, string, double>>();
L.Add(Tuple.Create("hi", "mom", 5.0));
More on the Tuple class.

You can also take a look at using anonymous types as an alternative to Tuples.
Example initialization of array of anon types and looping over the result:
var anons = new [] { new {num=1, str="str1"},
new {num=2, str="str2"} };
foreach(var v in anons) Console.WriteLine(v.num + " " + v.str);

If you are using C# 4.0, you can use the Tuple type

Have you looked at the Tuple class, introduced in .NET 4.0?
Another option is to use anonymous types.

The simplest way I can think of would be to use Tuples:
var L = new List<Tuple<string, string, double>>();
L.Add(Tuple.Create("a", "b", 10D));
Alternatively you could also use a list of dynamics

Related

Get first element from a dictionary

I have the following declaration:
Dictionary<string, Dictionary<string, string>> like = new Dictionary<string, Dictionary<string, string>>();
I need to get the first element out, but do not know the key or value. What's the best way to do this?
Note that to call First here is actually to call a Linq extension of IEnumerable, which is implemented by Dictionary<TKey,TValue>. But for a Dictionary, "first" doesn't have a defined meaning. According to this answer, the last item added ends up being the "First" (in other words, it behaves like a Stack), but that is implementation specific, it's not the guaranteed behavior. In other words, to assume you're going to get any defined item by calling First would be to beg for trouble -- using it should be treated as akin to getting a random item from the Dictionary, as noted by Bobson below. However, sometimes this is useful, as you just need any item from the Dictionary.
Just use the Linq First():
var first = like.First();
string key = first.Key;
Dictionary<string,string> val = first.Value;
Note that using First on a dictionary gives you a KeyValuePair, in this case KeyValuePair<string, Dictionary<string,string>>.
Note also that you could derive a specific meaning from the use of First by combining it with the Linq OrderBy:
var first = like.OrderBy(kvp => kvp.Key).First();
For anyone coming to this that wants a linq-less way to get an element from a dictionary
var d = new Dictionary<string, string>();
d.Add("a", "b");
var e = d.GetEnumerator();
e.MoveNext();
var anElement = e.Current;
// anElement/e.Current is a KeyValuePair<string,string>
// where Key = "a", Value = "b"
I'm not sure if this is implementation specific, but if your Dictionary doesn't have any elements, Current will contain a KeyValuePair<string, string> where both the key and value are null.
(I looked at the logic behind linq's First method to come up with this, and tested it via LinqPad 4)
Though you can use First(), Dictionaries do not have order per se. Please use OrderedDictionary instead. And then you can do FirstOrDefault. This way it will be meaningful.
EDIT:
Use an OrderedDictionary.
It's better to use FirstOrDefault() to retrieve the first value.
Ex:
var firstElement = like.FirstOrDefault();
string firstElementKey = firstElement.Key;
Dictinary<string,string> firstElementValue = firstElement.Value;
Dictionary does not define order of items. If you just need an item use Keys or Values properties of dictionary to pick one.
using System.Linq;
Dictionary<string, Dictionary<string, string>> like = new Dictionary<string, Dictionary<string, string>>();
Dictionary<string, string> first = like.Values.First();
ill find easy way to find first element in Dictionary :)
Dictionary<string, Dictionary<string, string>> like =
newDictionary<string,Dictionary<string, string>>();
foreach(KeyValuePair<string, Dictionary<string, string>> _element in like)
{
Console.WriteLine(_element.Key); // or do something
break;
}
convert to Array
var array = like.ToArray();
var first = array[0];
Easy way of to index a Collection in terms of performance, high compatibility (2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8) and easy implemention.
Save today!!
Its not only a items copy, this is items reference of a Collection!!
buy it!!
string [] arrayString = new string[like.Count];
like.Values.CopyTo( arrayString,0 );
arrayString[0] //First
References:
https://learn.microsoft.com/es-es/dotnet/api/system.collections.generic.icollection-1.copyto?view=net-5.0
https://social.msdn.microsoft.com/Forums/vstudio/en-US/dc5e4242-64d3-45ac-bdea-cf4f3d9abdbb/icollectioncopyto-vs-arraylisttoarray?forum=netfxbcl

Why using interface in Dictionary declaration?

I noticed this code in our project
Dictionary<int, IList> someDict = new Dictionary<int, IList>();
What's the idead of using interface for value? Does that means that I can put in every list that implements/support IList ? For example, can I put L List<int>and List<string> for values in the dictionary ?
It allows you to have a more generic type, so it will become easier to refactor if you change the type later.
List<T> or IList<T>
The best way to reduce refactoring job is to use IEnumerable when possible.
You can put any implementation of IList as a value
Dictionary<int, IList> someDict = new Dictionary<int, IList>();
someDict[1] = new List<string>() { "Hello", "World" };
someDict[2] = new List<int>() { 42 };
someDict[3] = new int[] { 1, 2, 3 };
someDict[4] = new ArrayList();
Yes, you want to be decoupled from a special class, you just want to make sure that the type used in the dictionary provides the IList funcionality. As long as your type provides this you can use it, including List<T>. It's like a contract which ensures a set of methods/properties on the type
Yes, you can use types that inherit from from type declared. In your case List<int> is generic type built from List<T>, which in turn inherits from IList. For that reason, yes, you can use List<int> in your dictionary.

Literal notation for Dictionary in C#?

I currently have a WebSocket between JavaScript and a server programmed in C#. In JavaScript, I can pass data easily using an associative array:
var data = {'test': 'val',
'test2': 'val2'};
To represent this data object on the server side, I use a Dictionary<string, string>, but this is more 'typing-expensive' than in JavaScript:
Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");
Is there some kind of literal notation for associative arrays / Dictionarys in C#?
You use the collection initializer syntax, but you still need to make a new Dictionary<string, string> object first as the shortcut syntax is translated to a bunch of Add() calls (like your code):
var data = new Dictionary<string, string>
{
{ "test", "val" },
{ "test2", "val2" }
};
In C# 6, you now have the option of using a more intuitive syntax with Dictionary as well as any other type that supports indexers. The above statement can be rewritten as:
var data = new Dictionary<string, string>
{
["test"] = "val",
["test2"] = "val2"
};
Unlike collection initializers, this invokes the indexer setter under the hood, rather than an appropriate Add() method.
While, the dictionary initializer answer is totally correct, there is another approach to this that I would point out (but I might not recommend it). If your goal is to provide terse API usage, you could use anonymous objects.
var data = new { test1 = "val", test2 = "val2"};
The "data" variable is then of an "unspeakable" anonymous type, so you could only pass this around as System.Object. You could then write code that can transform an anonymous object into a dictionary. Such code would rely on reflection, which would potentially be slow. However, you could use System.Reflection.Emit, or System.Linq.Expressions to compile and cache a delegate that would make subsequent calls much faster.
Asp.net MVC APIs use this technique in a number of places that I've seen. A lot of the Html Helpers have overloads that accept either an object or a dictionary. I assume the goal of their API design is the same as what you are after; terse syntax at the method call.
Use Dictionary Literals (C#9 proposal) [rejected] or the new syntax (beginning with C#9)
C#9 introduces a simpler syntax to create initialized Dictionary<TKey,TValue> objects without having to specify either the Dictionary type name or the type parameters. The type parameters for the dictionary are inferred using the existing rules used for array type inference.
// C# 1..8
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};
// C# 9
var x = ["foo":4, "bar": 5];
This synthax makes the work with dictionaries in C# simpler and removing the redundant code.
You can follow the issue on GitHub (and here is the milestone for C#9).
Edit: This proposal is currently rejected:
[...] We think there are a number of interesting use cases around initializing data, particularly for things like immutable dictionaries. We don't find the existing syntax for initializing a dictionary that onerous, nor do we see it as a frequent pattern in code that would benefit much from a language feature. We thing that the general area of initializing data should be looked at again after we do records and withers. [...]
current milestone:
Note that beginning with C# 9.0, constructor invocation expressions are target-typed. That is, if a target type of an expression is known, you can omit a type name, as the following example shows:
Dictionary<int, List<int>> lookup = new()
{
[1] = new() {1, 2, 3},
[2] = new() {5, 8, 3},
[5] = new() {1, 0, 4}
};
As the preceding example shows, you always use parentheses in a target-typed new expression.
If a target type of a new expression is unknown (for example, when you use the var keyword), you must specify a type name.
MSDN
Using DynamicObject, it is not that difficult to create a simpler dictionary initializer.
Imagine you want to call the following method
void PrintDict(IDictionary<string, object> dict) {
foreach(var kv in dict) {
Console.WriteLine (" -> " + kv.Key + " = " + kv.Value);
}
}
using a literal syntax like
var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);
This can be accomplished by creating a dynamic object like this
dynamic Dict {
get {
return new DynamicDictFactory ();
}
}
private class DynamicDictFactory : DynamicObject
{
public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
{
var res = new Dictionary<string, object> ();
var names = binder.CallInfo.ArgumentNames;
for (var i = 0; i < args.Length; i++) {
var argName = names [i];
if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
res [argName] = args [i];
}
result = res;
return true;
}
}

Practical example where Tuple can be used in .Net 4.0?

I have seen the Tuple introduced in .Net 4 but I am not able to imagine where it can be used. We can always make a Custom class or Struct.
That's the point - it is more convenient not to make a custom class or struct all the time. It is an improvement like Action or Func... you can make this types yourself, but it's convenient that they exist in the framework.
With tuples you could easily implement a two-dimensional dictionary (or n-dimensional for that matter). For example, you could use such a dictionary to implement a currency exchange mapping:
var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);
decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58
There's an excellent article in MSDN magazine that talks about the belly-aching and design considerations that went into adding Tuple to the BCL. Choosing between a value type and a reference type is particularly interesting.
As the article makes clear, the driving force behind Tuple was so many groups inside of Microsoft having a use for it, the F# team up front. Although not mentioned, I reckon that the new "dynamic" keyword in C# (and VB.NET) had something to do with it as well, tuples are very common in dynamic languages.
It is otherwise not particularly superior to creating your own poco, at least you can give the members a better name.
UPDATE: due for a big revision in C# version 7, now getting a lot more syntax love. Preliminary announcement in this blog post.
Here's a small example - say you have a method that needs to lookup a user's handle and email address, given a user Id. You can always make a custom class that contains that data, or use a ref / out parameter for that data, or you can just return a Tuple and have a nice method signature without having to create a new POCO.
public static void Main(string[] args)
{
int userId = 0;
Tuple<string, string> userData = GetUserData(userId);
}
public static Tuple<string, string> GetUserData(int userId)
{
return new Tuple<string, string>("Hello", "World");
}
I used a tuple to solve Problem 11 of Project Euler:
class Grid
{
public static int[,] Cells = { { 08, 02, 22, // whole grid omitted
public static IEnumerable<Tuple<int, int, int, int>> ToList()
{
// code converts grid to enumeration every possible set of 4 per rules
// code omitted
}
}
Now I can solve the whole problem with:
class Program
{
static void Main(string[] args)
{
int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
Console.WriteLine("Maximum product is {0}", product);
}
}
I could have used a custom type for this, but it would have looked exactly like Tuple.
C#'s tuple syntax is ridiculously bulky, so tuples are painful to declare. And it doesn't have pattern matching, so they're also painful to use.
But occasionally, you just want an ad-hoc grouping of objects without creating a class for it. For example, let's say I wanted to aggregate a list, but I wanted two values instead of one:
// sum and sum of squares at the same time
var x =
Enumerable.Range(1, 100)
.Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));
Instead of combining a collection of values into a single result, let's expand a single result into a collection of values. The easiest way to write this function is:
static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
Tuple<T, State> res;
while ((res = f(seed)) != null)
{
yield return res.Item1;
seed = res.Item2;
}
}
f converts some state into a tuple. We return the first value from the tuple and set our new state to the second value. This allows us to retain state throughout the computation.
You use it as such:
// return 0, 2, 3, 6, 8
var evens =
Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
.ToList();
// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
.Take(10).ToList();
evens is fairly straightforward, but fibs is a little more clever. Its state is actually a tuple which holds fib(n-2) and fib(n-1) respectively.
I don't like the abuse of them, since they produce code that doesn't explain itself, but they're awesome to implement on-the-fly compound keys, since they implement IStructuralEquatable and IStructuralComparable (to use both for lookup and ordering purposes).
And they combine all of their items' hashcodes, internally; for example, here is Tuple's GetHashCode (taken from ILSpy):
int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
{
return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
}
Tuples are great for doing multiple async IO operations at a time and returning all the values together. Here is the examples of doing it with and without Tuple. Tuples can actually make your code clearer!
Without (nasty nesting!):
Task.Factory.StartNew(() => data.RetrieveServerNames())
.ContinueWith(antecedent1 =>
{
if (!antecedent1.IsFaulted)
{
ServerNames = KeepExistingFilter(ServerNames, antecedent1.Result);
Task.Factory.StartNew(() => data.RetrieveLogNames())
.ContinueWith(antecedent2 =>
{
if (antecedent2.IsFaulted)
{
LogNames = KeepExistingFilter(LogNames, antecedent2.Result);
Task.Factory.StartNew(() => data.RetrieveEntryTypes())
.ContinueWith(antecedent3 =>
{
if (!antecedent3.IsFaulted)
{
EntryTypes = KeepExistingFilter(EntryTypes, antecedent3.Result);
}
});
}
});
}
});
With Tuple
Task.Factory.StartNew(() =>
{
List<string> serverNames = data.RetrieveServerNames();
List<string> logNames = data.RetrieveLogNames();
List<string> entryTypes = data.RetrieveEntryTypes();
return Tuple.Create(serverNames, logNames, entryTypes);
}).ContinueWith(antecedent =>
{
if (!antecedent.IsFaulted)
{
ServerNames = KeepExistingFilter(ServerNames, antecedent.Result.Item1);
LogNames = KeepExistingFilter(LogNames, antecedent.Result.Item2);
EntryTypes = KeepExistingFilter(EntryTypes, antecedent.Result.Item3);
}
});
If you were using an anonymous function with an implied type anyway then you aren't making the code less clear by using the Tuple. Retuning a Tuple from a method? Use sparingly when code clarity is key, in my humble opinion. I know functional programming in C# is hard to resist, but we have to consider all of those old clunky "object oriented" C# programmers.
Tuples are heavily used in functional languages which can do more things with them, now F# is a 'official' .net language you may want to interoperate with it from C# and pass them between code written in two languages.
I tend to avoid Tuple for most scenarios since it hurts readability. However, Tuple is useful when you need to group unrelated data.
For example, suppose you have a list of cars and the cities in which they were purchased:
Mercedes, Seattle
Mustang, Denver
Mercedes, Seattle
Porsche, Seattle
Tesla, Seattle
Mercedes, Seattle
You want to aggregate the counts for each car per city:
Mercedes, Seattle [3]
Mustang, Denver [1]
Porsche, Seattle [1]
Tesla, Seattle [1]
To do this, you create a Dictionary. You have a few options:
Create a Dictionary<string, Dictionary<string, int>>.
Create a Dictionary<CarAndCity, int>.
Create a Dictionary<Tuple<string, string>, int>.
Readability is lost with the first option. It will require you to write a lot more code.
The second option works and is succinct, but car and city aren't really related and probably don't belong in a class together.
The third option is succinct and clean. It's a good use of Tuple.
A few examples off the top of my head:
An X and Y location (and Z if you like)
a Width and Height
Anything measured over time
For example you wouldn't want to include System.Drawing in a web application just to use Point/PointF and Size/SizeF.
You should be very careful with using Tuple and probably think twice before do this. From my previous experience I found out that using Tuple makes code very difficult to read and support in the future. A while ago, I had to fix some code where tuples were used almost everywhere. Instead of thinking about proper object models, they just used tuples. That was nightmare... sometimes I wanted to kill the guy who wrote the code...
Don't want to say that you shouldn't use Tuple and it's evil or something and I'm hundred percent sure there are some tasks where the Tuple is the best candidate to be used, but probably you should think again, do you REALLY need it?
The best use for Tuples I have found is when needing to return more than 1 type of object from a method, you know what object types and number they will be, and it is not a long list.
Other simple alternatives would be using an 'out' parameter
private string MyMethod(out object)
or making a Dictionary
Dictionary<objectType1, objectType2>
Using a Tuple however saves either creating the 'out' object or having to essentially look-up the entry in the dictionary;
Just found the solution of one of my issues in Tuple. It is like declaring a class in scope of a method, but with lazy declaration of its fields names. You operate with collections of tuples, its single instances and then create a collection of anonymous type with the required field names, basing on your tuple. This avoids you from creating the new class for this purpose.
The task is to write a JSON response from LINQ without any additional classes:
//I select some roles from my ORM my with subrequest and save results to Tuple list
var rolesWithUsers = (from role in roles
select new Tuple<string, int, int>(
role.RoleName,
role.RoleId,
usersInRoles.Where(ur => ur.RoleId == role.RoleId).Count()
));
//Then I add some new element required element to this collection
var tempResult = rolesWithUsers.ToList();
tempResult.Add(new Tuple<string, int, int>(
"Empty",
-1,
emptyRoleUsers.Count()
));
//And create a new anonimous class collection, based on my Tuple list
tempResult.Select(item => new
{
GroupName = item.Item1,
GroupId = item.Item2,
Count = item.Item3
});
//And return it in JSON
return new JavaScriptSerializer().Serialize(rolesWithUsers);
Of cause we could do this with declaring a new Class for my groups, but the idea to create such an anonimous collections without declaring of new classes.
Well in my case, I had to use a Tuple when I found out that we cannot use out parameter in an asynchronous method. Read about it here. I also needed a different return type. So I used a Tuple instead as my return type and marked the method as async.
Sample code below.
...
...
// calling code.
var userDetails = await GetUserDetails(userId);
Console.WriteLine("Username : {0}", userDetails.Item1);
Console.WriteLine("User Region Id : {0}", userDetails.Item2);
...
...
private async Tuple<string,int> GetUserDetails(int userId)
{
return new Tuple<string,int>("Amogh",105);
// Note that I can also use the existing helper method (Tuple.Create).
}
Read more about Tuple here.
Hope this helps.
Changing shapes of objects when you need to send them across wire or pass to different layer of application and multiple objects get merged into one:
Example:
var customerDetails = new Tuple<Customer, List<Address>>(mainCustomer, new List<Address> {mainCustomerAddress}).ToCustomerDetails();
ExtensionMethod:
public static CustomerDetails ToCustomerDetails(this Tuple<Website.Customer, List<Website.Address>> customerAndAddress)
{
var mainAddress = customerAndAddress.Item2 != null ? customerAndAddress.Item2.SingleOrDefault(o => o.Type == "Main") : null;
var customerDetails = new CustomerDetails
{
FirstName = customerAndAddress.Item1.Name,
LastName = customerAndAddress.Item1.Surname,
Title = customerAndAddress.Item1.Title,
Dob = customerAndAddress.Item1.Dob,
EmailAddress = customerAndAddress.Item1.Email,
Gender = customerAndAddress.Item1.Gender,
PrimaryPhoneNo = string.Format("{0}", customerAndAddress.Item1.Phone)
};
if (mainAddress != null)
{
customerDetails.AddressLine1 =
!string.IsNullOrWhiteSpace(mainAddress.HouseName)
? mainAddress.HouseName
: mainAddress.HouseNumber;
customerDetails.AddressLine2 =
!string.IsNullOrWhiteSpace(mainAddress.Street)
? mainAddress.Street
: null;
customerDetails.AddressLine3 =
!string.IsNullOrWhiteSpace(mainAddress.Town) ? mainAddress.Town : null;
customerDetails.AddressLine4 =
!string.IsNullOrWhiteSpace(mainAddress.County)
? mainAddress.County
: null;
customerDetails.PostCode = mainAddress.PostCode;
}
...
return customerDetails;
}
An out parameter is great when there are only a few values that need to be returned,
but when you start encountering 4, 5, 6, or more values that need to be returned, it
can get unwieldy. Another option for returning multiple values is to create and return
a user-defined class/structure or to use a Tuple to package up all the values that need
to be returned by a method.
The first option, using a class/structure to return the values, is straightforward. Just
create the type (in this example it is a structure) like so:
public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}
The second option, using a Tuple, is an even more elegant solution than using a userdefined
object. A Tuple can be created to hold any number of values of varying types.
In addition, the data you store in the Tuple is immutable; once you add the data to
the Tuple through the constructor or the static Create method, that data cannot be
changed.
Tuples can accept up to and including eight separate values. If you need to return
more than eight values, you will need to use the special Tuple class:
Tuple Class
When creating a Tuple with more than eight values, you cannot use the static Create
method—you must instead use the constructor of the class. This is how you would
create a Tuple of 10 integer values:
var values = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> (
1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int> (8, 9, 10));
Of course, you can continue to add more Tuples to the end of each embedded Tuple,
creating any size Tuple that you need.
Only for prototyping - Tuples are meaningless. It convenient to use them but it's a shortcut only! For prototypes - fine. Just be sure to delete this code later.
It easy to write, hard to read. It has no visible advantages over classes, inner classes , anonymous classes etc.
Well I tried 3 ways to solve the same problem in C#7 and I have found a use case for Tuples.
Working with dynamic data in web projects can sometimes be a pain when mapping etc.
I like the way the Tuple just auto mapped onto item1, item2, itemN which seems more robust to me than using array indexes where you might get caught on an out of index item or using the anonymous type where you may misspell a property name.
It feels like a DTO has been created for free just by using a Tuple and I can access all the properties using itemN which feels more like static typing without having to create a separate DTO for that purpose.
using System;
namespace Playground
{
class Program
{
static void Main(string[] args)
{
var tuple = GetTuple();
Console.WriteLine(tuple.Item1);
Console.WriteLine(tuple.Item2);
Console.WriteLine(tuple.Item3);
Console.WriteLine(tuple);
Console.WriteLine("---");
var dyn = GetDynamic();
Console.WriteLine(dyn.First);
Console.WriteLine(dyn.Last);
Console.WriteLine(dyn.Age);
Console.WriteLine(dyn);
Console.WriteLine("---");
var arr = GetArray();
Console.WriteLine(arr[0]);
Console.WriteLine(arr[1]);
Console.WriteLine(arr[2]);
Console.WriteLine(arr);
Console.Read();
(string, string, int) GetTuple()
{
return ("John", "Connor", 1);
}
dynamic GetDynamic()
{
return new { First = "John", Last = "Connor", Age = 1 };
}
dynamic[] GetArray()
{
return new dynamic[] { "John", "Connor", 1 };
}
}
}
}

.NET / C# - Convert List to a SortedList

What is the best way to convert a List to SortedList? Any good way to do it without cycling through it? Any clever way to do it with an OrderBy()?
WRAP UP
Please read all answers and comments.
Do you mean:
you have a List<T> and wish it to be sorted in place?
you have a List<T> and wish to create another 'list' which is itself sorted
you have a List<T> and wish to make a SortedList<T,T> where the key is the same as the value
Assuming input:
var x = new List<int>() { 3, 2, 1 };
1 is trivial
x.Sort();
2 is trivial
// sx is an IOrderedEnumerable<T>, you can call ToList() on it if you want
var sx = x.OrderBy(i => i);
3 is trivial with a copy
var s = new SortedList<int,int>(t.ToDictionary(i => i));
and more efficiently:
var s = new SortedList<int,int>();
foreach (var i in x) { s[i] = [i]; }
I can't see why you would want to do 3 but there you go.
var list = new List<string>();
var sortedList = new SortedList<string, string>(list.ToDictionary(s => s));
Now I have no clue how efficient this is, but it's one line of code :) Also, in this example I just used the string itself as the selector. In a real scenario, you should know ahead of time what you'd like to use as a selector.
Understand that a List<T> is a smart array, and a SortedList<T, U> is a key/value binary tree. Since there's no relationship between their structures, there can't possibly be a more effective way to do it rather than simply taking each element from the list and putting it into the tree.
If you mean "sorted list" instead of "SortedList," then it's trivial to sort your list via either List.Sort() or an appropriate OrderBy().
List unsortedPersons = new List();
// ... Populate unsortedPersons ...
var sorted = from person in unsortedPersons
orderby person.Name
select person;
The LINQ gives you an ISortedEnumerable i believe, which may be good enough for your purposes.

Categories