C# and arrays of anonymous objects - c#

What does such an expression mean?
obj.DataSource = new[]
{
new {Text = "Silverlight", Count = 10, Link="/Tags/Silverlight" },
new {Text = "IIS 7", Count = 11, Link="http://iis.net" },
new {Text = "IE 8", Count = 12, Link="/Tags/IE8" },
new {Text = "C#", Count = 13, Link="/Tags/C#" },
new {Text = "Azure", Count = 13, Link="?Tag=Azure" }
};
Especially these lines: new {Text = "IIS 7"... }
How can I create an array like this manually to suit this DataSource.

First, let's reformat that code a little:
obj.DataSource = new[]
{
new { Text = "Silverlight", Count = 10, Link = "/Tags/Silverlight" },
new { Text = "IIS 7", Count = 11, Link = "http://iis.net" },
new { Text = "IE 8", Count = 12, Link = "/Tags/IE8" },
new { Text = "C#", Count = 13, Link = "/Tags/C#" },
new { Text = "Azure", Count = 13, Link = "?Tag=Azure" }
};
This does not look like a multi-dimensional array, but rather like an array of 5 objects. These objects inside the array are of an anonymous type, created and initialized using new { ... }.
Concerning your question how you can manually create such an array to suit the data source: you seem to be doing exactly that with the above code.

That's not a multidimensional array. That's an array of objects which have been created using object initializers with anonymous types.

Looks like an array of anonymous types.
http://msdn.microsoft.com/en-us/library/bb397696.aspx

Just to add: Anonymous types are converted by the compiler to a real object. So the code will be changed to something equivalent of this (MUCH simplified, only to show that the compiler will create an actual class):
internal sealed class AnonymousClass1
{
internal string Text { get; set; }
internal int Count { get; set; }
internal string Link { get; set; }
}
And your code will then be changed to:
obj.DataSource = new AnonymousClass1[]
{
new AnonymousClass1 {Text = "Silverlight", Count = 10, Link="/Tags/Silverlight" },
new AnonymousClass1 {Text = "IIS 7", Count = 11, Link="http://iis.net" },
new AnonymousClass1 {Text = "IE 8", Count = 12, Link="/Tags/IE8" },
new AnonymousClass1 {Text = "C#", Count = 13, Link="/Tags/C#" },
new AnonymousClass1 {Text = "Azure", Count = 13, Link="?Tag=Azure" }
};
In one of my programs, I have code like this (simplified!):
var myObjects = new []{
new { Id = Guid.NewGuid(), Title = "Some Title", Description = string.Empty },
new { Id = Guid.NewGuid(), Title = "Another Title", Description = string.Empty },
new { Id = Guid.NewGuid(), Title = "Number 3", Description = "Better than No2, but not much" }
}
foreach(var myObject in myObjects) {
DoSomeThingWith(myObject.Title);
}
This works because it is just another class (I even get IntelliSense) behind the scenes. The benefit is obviously that I just saved myself from creating a class for this object. In my example, all objects need to look the same as well. (Obviously, doing this for any public members would be a bad idea as the compiler might change the name of the anonymous class if you add/remove some)

It's making a new object array, containing a group of anonymous objects.
new {Text = "Azure", Count = 13, Link="?Tag=Azure" }
is not creating a hash like similar syntax in say php would, but rather real a real object with the properties Test, Count, and Link set.
A good primer for anonymous objects can be found here
You should be able to use the same syntax to create new structures like this, the property values do not have to be constants:
string text = "Azure";
int count = 13;
string link = "?Tag=Azure";
new {Text = text, Count = count, Link=link }

To return such an array from a function I used:
public object GetAnonymousArray()
{
var tbl = new List<object>();
while (___)
{
//fill array in cycle
tbl.Add(new {Text = someString, Count = someInt, Link = link});
}
return tbl;
}

Related

converting int to List<double?>, ChartJS Core

I'm working on a web application. I found this interesting https://github.com/mattosaurus/ChartJSCore. to use charts in my application.
The charts are working successfully in most pages. But in one page i have the following idea:
I have 3 properties (Appropriate, Inappropriate, NoInteraction) in my model all with type (int) and i need to keep it as integer to manipulate other functionalities in the application. Each property will be represented as one series in the chart and it should be list or array of 15 integer always.
Here is my properties in Session Model:
public int DayNumber { get; set; }
public int Appropriate { get; set; }
public int NotAppropriate { get; set; }
public int NoInteraction { get; set; }
Here is my Controller:
public IActionResult Details()
{
var result = _db.Session.ToList();
//I want this appropriateLine to be passed to GenerateLineChart method but whenever i tried i came up with an error of converting types.
var AppropriateLine = result.Select(x => x.Appropriate).ToList();
Chart lineChart = GenerateLineChart();
ViewData["LineChart"] = lineChart;
return View();
}
private static Chart GenerateLineChart()
{
Chart chart = new Chart();
chart.Type = Enums.ChartType.Line;
ChartJSCore.Models.Data data = new ChartJSCore.Models.Data();
data.Labels = new List<string>() { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
LineDataset AppropriateDataset = new LineDataset()
{
Label = "Appropriate Data Line",
Data = new List<double?>() { 2, 6, 2, 6, 2, 6 }, //Here i want this to be filled with data from AppropriateLine variable, it works for the fixed value only
Fill = "false",
LineTension = 0.1,
BackgroundColor = ChartColor.FromHexString("#FF6384"),
BorderColor = ChartColor.FromHexString("#FF6384"),
BorderCapStyle = "butt",
BorderDash = new List<int> { },
BorderDashOffset = 0.0,
BorderJoinStyle = "miter",
PointBorderColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointBackgroundColor = new List<ChartColor>() { ChartColor.FromHexString("#fff") },
PointBorderWidth = new List<int> { 1 },
PointHoverRadius = new List<int> { 5 },
PointHoverBackgroundColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointHoverBorderColor = new List<ChartColor>() { ChartColor.FromHexString("#FF6384"), },
PointHoverBorderWidth = new List<int> { 2 },
PointRadius = new List<int> { 1 },
PointHitRadius = new List<int> { 10 },
SpanGaps = false
};
data.Datasets = new List<Dataset>();
data.Datasets.Add(AppropriateDataset);
Options options = new Options()
{
Scales = new Scales()
};
Scales scales = new Scales()
{
YAxes = new List<Scale>()
{
new CartesianScale()
}
};
CartesianScale yAxes = new CartesianScale()
{
Ticks = new Tick()
};
Tick tick = new Tick()
{
Callback = "function(value, index, values) {return '' + value;}"
};
yAxes.Ticks = tick;
scales.YAxes = new List<Scale>() { yAxes };
options.Scales = scales;
chart.Options = options;
chart.Data = data;
return chart;
}
How can i implement this "Explicit Casting" of appropriateLine variable which is (int) before passing it to GenerateLineChart().
Note that i don't want to change Model properties type since many functions depend on it. Also, I cannot change Data type from List<double?> since many other problems solved by adding this.
I tried many casting solutions but none of them works for me such as:
(List<double?>)result.Select(x => x.Appropriate);
private static Chart GenerateLineChart((List<double?>)AppropriateLine)
I've read about "Convert all" method but not worked.
Any help is much appreciated,
Thanks in advance.
Based on what you mention, it seems that the data passed to GenerateLineChart will only be used for UI purposes. That is, this method can get an appropriate copy of the original data. If this is the case, then, the solution you attempted with
(List<double?>)result.Select(x => x.Appropriate)
was very close, but the cast needs to be done inside Select, i.e.
result.Select(x => (double?)x.Appropriate)
Here is a sketch of your code with that change
public IActionResult Details()
{
var result = _db.Session.ToList();
var AppropriateLine = result.Select(x => (double?)x.Appropriate).ToList();
var lineChart = GenerateLineChart(AppropriateLine);
// Rest or your code
}
private static Chart GenerateLineChart(IEnumerable<double?> data)
{
// Your code as is here ....
LineDataset AppropriateDataset = new LineDataset()
{
Data = data,
// Rest of your code
}
// ....
}
maybe you can check at the moment that you need the list if the number is double or int bool isInt = d == (int)d; and parse to use it only for that time on an aux.

How to filter List<object> using Linq/Lambda

Here is my scenario
List<object> obj = new List<object>();
obj.Add(new {id = 1, name = "Jakob"});
obj.Add(new {id = 2, name = "Sam"});
obj.Add(new {id = 3, name = "Albert"});
obj.Add(new {id = 1, name = "Jakob"});
How do you filter List<object> like these so it returns a List of users with name "Jakob"?
obj.Where(t => t.name == "Jakob") doesn't work
The best option you have is to declare a class that represents a user.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
Then create a list of User objects and query this list.
var users = new List<User>
{
new User { Id = 1, Name = "Jakob" },
new User { Id = 2, Name = "Sam" },
new User { Id = 3, Name = "Albert" }
}
var filteredUsers = users.Where(user => user.Name == "Jakob");
Otherwise, you have to rely on the solution that Tengiz suggested.
If you convert your object to dynamic, it should work:
obj.Where(t => ((dynamic)t).name == "Jakob")
EDIT:
For completeness, I should mention couple of things:
Usage of dynamic type comes down to usage of object with reflection on top of it, so eventually you don't get something better than reflection if you use this approach.
Usage of dynamic at all involves loading necessary assemblies (a.k.a. DLR) into CLR, which would not load if you don't use dynamic at all. In other words, it's an overhead.
So, use with your own discretion.
Yet another alternative is create array of anonymous types and then convert it to list via ToList IEnumerable extension method:
var obj = (new[] {
new { id = 1, name = "Jakob" },
new { id = 2, name = "Sam" },
new { id = 3, name = "Albert" },
new { id = 1, name = "Jakob" }}).ToList();
obj.Where(c => c.name == "Jakob");
If you don't really need a list and array is fine too - just don't convert to list. Benefit is you got strongly typed list and not list of arbitrary objects.
You could use reflection
var l = new List<object>();
l.Add(new {key = "key1", v = "value1"});
l.Add(new {key = "key2", v = "value2", v2="another value"});
l.Add(new {key = "key3", v = "value3", v3= 4});
l.Add(new {key = "key4", v = "value4", v4 = 5.3});
var r = l.Where(x=> (string)x.GetType().GetProperty("key")?.GetValue(x) == "key1");
Get the type of your elements and find the property you are looking for. Then get the value for the current instance and compare it to the value you want to filter for.
But on the other hand, this approach has the advantage of working even if the List contains items of several different anonymous types (if they have different properties), as long as they all have the property you are filtering for.
EDIT
With c# 6 you can use the ? operator, which is sort of an inline check for null. Ie, if GetProperty() returns null because the property is not found, the expression returns null without executing GetValue() (which would otherwise throw a NullReferenceException)

Why does using IEnumerable<T> inside a recursive method make it much slower than using a List<T>?

I am using a recursive method to go through a tree of items and add its children to a flat collection:
public class Thing
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
}
void Main()
{
var sampleData = new List<Thing>
{
new Thing { Id = 1, Name = "root1", ParentId = null },
new Thing { Id = 2, Name = "2", ParentId = 1 },
new Thing { Id = 3, Name = "3", ParentId = 1 },
new Thing { Id = 4, Name = "4", ParentId = 2 },
new Thing { Id = 5, Name = "5", ParentId = 2 },
new Thing { Id = 6, Name = "6", ParentId = 2 },
new Thing { Id = 7, Name = "7", ParentId = 6 },
new Thing { Id = 8, Name = "8", ParentId = 7 },
new Thing { Id = 9, Name = "9", ParentId = 8 },
new Thing { Id = 10, Name = "10", ParentId = 9 },
new Thing { Id = 11, Name = "11", ParentId = 10 },
new Thing { Id = 12, Name = "12", ParentId = 11 },
new Thing { Id = 13, Name = "13", ParentId = 12 },
new Thing { Id = 14, Name = "14", ParentId = 13 },
new Thing { Id = 15, Name = "root15", ParentId = null }
};
var subThings = new HashSet<Thing>();
var stopWatch = new Stopwatch();
stopWatch.Start();
//AddSubThings(subThings, sampleData, new List<int> { 1 });
AddSubThingsUsingList(subThings, sampleData, new List<int> { 1 });
stopWatch.Elapsed.Dump();
subThings.Dump();
}
private void AddSubThings(HashSet<Thing> resultThings, IEnumerable<Thing> sourceThings, IEnumerable<int> parentIds)
{
if (!sourceThings.Any() || !parentIds.Any())
{
return;
}
var subThings = sourceThings.Where(st => st.ParentId.HasValue && parentIds.Contains(st.ParentId.Value));
resultThings.UnionWith(subThings);
AddSubThings(resultThings, sourceThings.Except(subThings), subThings.Select(st => st.Id));
}
private void AddSubThingsUsingList(HashSet<Thing> resultThings, List<Thing> sourceThings, List<int> parentIds)
{
if (!sourceThings.Any() || !parentIds.Any())
{
return;
}
var subThings = sourceThings.Where(st => st.ParentId.HasValue && parentIds.Contains(st.ParentId.Value));
resultThings.UnionWith(subThings);
AddSubThingsUsingList(resultThings, sourceThings.Except(subThings).ToList(), subThings.Select(st => st.Id).ToList());
}
When I use the AddSubThings method it takes around 90 seconds to process. However if I use the AddSubThingsUsingList method it does not even take a second. Why is this?
The problem is because your create subThings from sourceThings like this
var subThings = sourceThings.Where(
st => st.ParentId.HasValue && parentIds.Contains(st.ParentId.Value));
Then you pass the following as sourceThings to the recursive call.
sourceThings.Except(subThings)
Which is equivalent to
sourceThings.Except(
sourceThings.Where(
st => st.ParentId.HasValue && parentIds.Contains(st.ParentId.Value)))
That query when iterated with have to iterate over the original list twice. With each recursive call the query will build up and need to iterate the original list 2^n times where n is the recursion level. And your query is being iterated by the Any and the HashSet.UnionWith calls meaning it's more like 2^(n+1).
The other one immediately iterates the query before passing them and thus avoids this doubling problem.
You could pass the following to your recursive call for sourceThings instead to make it faster as it doesn't double up the required iterating of the original list on each recursive call.
sourceThings.Where(st => !st.ParentId.HasValue || !parentIds.Contains(st.ParentId.Value))
Ok. This is a bit complex.
Operations on IEnumerable are lazy, i.e. they are not executed until you need the result. Now when you pass sourceThins and subThings to AddSubThings, you've not sent a materialized collection of things, all you've done is you've defined how these collections are calculated from the original Lists.
Now when the method calls itself recursively, it adds more filtering and selection to the data it has received.
All these layers of selection and filtering will be called when you call Any().
On the other hand, in the case of Lists, things are materialized after calls to Where, Except and Select, because you call ToList.

C# Dynamic array

I want an array to contain strings, floats and ints that can be accessed via an index key.
I have an example in Lua how you would do but I don't know how you do it in C#
bookArray = [];
bookArray[1] =
{
Name = "Book 1";
Price = 50;
WPP = 374;
Pages = 42;
}
You may create a class and use List<MyClass>
class MyClass
{
public string Name {get;set;}
public double Price {get;set;}
public int Pages {get;set;}
}
Here is the list:
List<MyClass> values = new List<MyClass>();
Adding item
values.Add(new MyClass(){Name = "Book 1", Pages = 42, Price=50.0});
Insert at specific index:
values.Insert(0,new MyClass(){Name = "Book 2", Pages = 432, Price=10.0});
Retrieve at specific index:
MyClass theClass = values[1];
If you are ok with your inner type being immutable, you could do this:
var ar = new[] {
new { Name = "Book 1", Price = 50, WPP = 374, Pages = 42 },
new { Name = "Book 2", Price = 55, WPP = 220, Pages = 129 }
};
Which is about as close as you can come to the Lua definition

Instantiating nested classes shorthand

I am trying to Fill a list of objects in this format so that it matches my JSON.NEt output for a needed API. But I am getting a NullReferenceException on the whole block starting with .Add()...Am I missing something?
foreach(var item in emailsToUpload.payload)
{
hubPayload.Add(new HubEmailItem()
{
email = item.Email, properties =
{ new HubEmailTuple() { property = "date", value = (DateTime.Now).ToString("d") },
new HubEmailTuple() { property = "other property", value = "other value" }
}
});
}
Update:
public class HubEmailItem
{
public String email { get; set; }
public List<HubEmailTuple> properties { get; set; }
}
You can't use this syntax with generic lists like this.
properties =
{ new HubEmailTuple() { property = "date", value = (DateTime.Now).ToString("d") },
new HubEmailTuple() { property = "other property", value = "other value" }
}
You should add a new List<HubSpotEmailTuple>
properties = new List<HubSpotEmailTuple>
{ new HubEmailTuple() { property = "date", value = (DateTime.Now).ToString("d") },
new HubEmailTuple() { property = "other property", value = "other value" }
}
Note: This is valid:
int[] a = {0, 2, 4, 6, 8};
But this is not:
// wrong
List<int> a = {0, 2, 4, 6, 8};
// correct
List<int> a = new List<int> {0, 2, 4, 6, 8};
Take a look at documentation: http://msdn.microsoft.com/en-us/library/aa664573(v=vs.71).aspx
The only thing that could throw this exception in case the List is initialized is one of the items you are iterating through. You are using the Email property and it seems that one of the items is null and is causing the exception.
email = item.Email //causes NullReferenceException when item is null
You can check if this is indeed true by setting a conditional breakpoint at the first curly brace of the foreach loop that will be triggered when item == null is true.

Categories