C# jagged array get property instantiate linq - c#

I have a Model object that contains a list of node. These nodes contain a signature.
I would like to have a property with a getter returning an array of signatures. I have trouble to instantiate the array and I'm not sure if I should use an array/list/enumerable or something else.
How would you achieve this?
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
internal class Program
{
private static void Main(string[] args)
{
var m = new Model();
Console.WriteLine(m.Signatures.ToString());
Console.ReadLine();
}
}
public class Model
{
public List<Node> Nodes { get; set; }
public int[][] Signatures
{
get
{
return Nodes.Select(x => x.Signature) as int[][];
}
}
public Model()
{
Nodes = new List<Node>();
Nodes.Add(new Node { Signature = new[] { 1,1,0,0,0 } });
Nodes.Add(new Node { Signature = new[] { 1,1,0,0,1 } });
}
}
public class Node
{
public int[] Signature { get; set; }
}
}

Use ToArray()
return Nodes.Select(x => x.Signature).ToArray();
And something like this to output it correctly:
Array.ForEach(m.Signatures, x=>Console.WriteLine(string.Join(",", x)));

In your Signatures property you try to use the as operator to convert the type into int[][]. The Select method however returns an IEnumerable<int[]> which is not an array. Use ToArray to create the array:
public int[][] Signatures
{
get
{
return Nodes.Select(x => x.Signature).ToArray();
}
}

Related

Why do I get 'foreach statement cannot operate on variables of type 'object'' when the object is type IList

I am trying to iterate over a list that I grab by doing solutionInformation.GetType().GetProperties().GetValue(). But even though the type is an IList, I get an exception when I try to iterate over the value.
namespace NS
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Accelerator
{
public string AccName { get; set; }
}
public class DeviceInfo
{
public int Ram { get; set; }
public List<Accelerator> Accelerator { get; set; }
}
public class SolutionPods
{
public DeviceInfo DeviceInfo { get; set; }
}
public class Solution
{
public List<SolutionPods> SolutionPods { get; set; }
}
public class HelloWorld
{
public static void Main(string[] args)
{
var acc1 = new Accelerator { AccName = "accelerator Name" };
List<Accelerator> accList1 = new List<Accelerator>();
accList1.Add(acc1);
var devInfo1 = new DeviceInfo { Ram = 64, Accelerator = accList1 };
var solComponet = new SolutionPods { DeviceInfo = devInfo1 };
List<SolutionPods> SCList = new List<SolutionPods>();
SCList.Add(solComponet);
var solution = new Solution { SolutionPods = SCList };
foreach (var solutionComponet in solution.SolutionPods)
{
var solutionInformation = solutionComponet.DeviceInfo;
foreach (var solutionProperty in solutionInformation.GetType().GetProperties())
{
var solutionValue = solutionProperty.GetValue(solutionInformation);
if (solutionValue is IList)
{
Console.WriteLine("IList found");
// System.Collections.Generic.List`1[NS.Accelerator]
Console.WriteLine(solutionValue);
/*
/tmp/AFBHdRy49g.cs(64,43): error CS1579: foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public instance definition for 'GetEnumerator'
*/
foreach (var s in solutionValue)
{
Console.WriteLine(s);
}
}
}
}
Console.WriteLine("Setup Complete");
}
}
}
Am I not actually grabbing a list? Or do I need to convert the object into a different form so that it has an GetEnumerator property?
In C#, once a variable is declared, it keeps the type it's declared as. In your case, the var solutionValue uses the inferred type of object because that's what Property.GetValue() returns.
The compiler does not implement type narrowing when it encounters a conditional like this:
if (solutionValue is IList)
However, you can use pattern matching to declare a new variable with the correct type:
if (solutionValue is IList solutions)
{
...
foreach (var s in solutions)
The compiler does a static type check that the value provided is (statically) an IEnumerable. An object is not. A (IList)solutionValue would be.
if (solutionValue is IList list) // joining a type test and a cast
{
foreach (var s in list) // here list is an IList
{
Console.WriteLine(s);
}
}

List.ToArray() - why is the array empty?

I'm writing a serializable object that contains a collection. So, in order to be able to add and remove items from that collection, I added methods that would first convert the collection from an Array into a List, add or remove the items and then convert the List back into a Array.
public void AddElement(Element element) {
List<Element> list = new List<Element>(this.elements);
list.Add(element);
this.elements = list.ToArray();
}
Is there maybe a problem creating the List like this?
List(this.elements)
Or is it a problem, that the Array is Length is 0 at start?
EDIT1: converting from a list field also leaves an empty array.
EDIT2: XML Serialization is not wanted.
Your code works fine. Here is the MCVE:
Program.cs
using System;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
var test = new TestClass();
test.AddElement(new Element());
Console.WriteLine(test.HowMuch());
}
}
}
TestClass.cs
using System.Collections.Generic;
namespace Test1
{
class TestClass
{
private Element[] elements = new Element[0];
public void AddElement(Element element)
{
List<Element> list = new List<Element>(this.elements);
list.Add(element);
this.elements = list.ToArray();
}
public int HowMuch()
{
return elements.Length;
}
}
}
Element.cs
namespace Test1
{
class Element
{
}
}
The example outputs 1, not 0.
The most probable reason is that you assign this.elements to a variable, hence, store old version of the array.

Failing to read XML content using XmlSerializer

I got this in my class:
namespace MSAToolsLibrary.PublisherEntry
{
[XmlRoot(ElementName = "PublisherDatabase", Namespace = "http://www.publictalksoftware.co.uk/msa")]
public class PublisherData
{
public PublisherData()
{
//_Publishers = new List<Publisher>();
_PublishersDictionary = new Dictionary<string, Publisher>();
}
public List<Publisher> Publishers
{
get { return _PublishersDictionary.Select(x => x.Value).ToList(); }
set { _PublishersDictionary = value.ToDictionary(x => x.Name, x => x); }
}
private Dictionary<string, Publisher> _PublishersDictionary;
[XmlIgnore]
public Dictionary<string, Publisher> PublisherDictionary
{
get { return _PublishersDictionary; }
}
public void AddPublisher(String strName, String strNotes, Gender eGender, Appointed eAppointedAs, Serving eServingAs, bool bUseForDemonstrations, bool bAvailableMidweek, bool bAvailableWeekend, DateTime[] listDatesNotAvailable)
{
Publisher _Publisher = new Publisher()
{
Name = strName,
Notes = strNotes,
Gender = eGender,
AppointedAs = eAppointedAs,
ServingAs = eServingAs,
};
_Publisher.Assignments.UseForDemonstrations = bUseForDemonstrations;
_Publisher.Availability.Midweek = bAvailableMidweek;
_Publisher.Availability.Weekend = bAvailableWeekend;
_Publisher.Availability.DatesNotAvailable = new List<DateTime>(listDatesNotAvailable);
//_Publishers.Add(_Publisher);
_PublishersDictionary.Add(strName, _Publisher);
}
}
}
Now, when I save my data to XML it all works good.
But when I read in:
public void ReadPublisherData(out Int64 iResult)
{
_PublisherData.Publishers.Clear(); // Reset
iResult = MakeResult(true);
try
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
iResult = _PublisherData.PublisherDictionary.Count;
}
}
catch
{
iResult = MakeResult(false);
}
}
Doesn't work. I have zero publishers in the list or the dictionary.
What am I doing wrong?
Update
If I change the PublisherData declaration so that it has the needed back field:
public PublisherData()
{
_Publishers = new List<Publisher>();
_PublishersDictionary = new Dictionary<string, Publisher>();
}
public List<Publisher> Publishers
{
get => _Publishers; set => _Publishers = value;
}
private List<Publisher> _Publishers;
Then this causes the data to serialize correctly and I get what is expected in the MFC application. But now my PublisherDictionary is hanging. So I added a function:
public void BuildPublisherDictionary()
{
_PublishersDictionary = _Publishers.ToDictionary(x => x.Name, x => x);
}
And adjusted the read routine:
public void ReadPublisherData(out Int64 iResult)
{
iResult = MakeResult(true);
try
{
_PublisherData.Publishers.Clear(); // Reset
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamReader reader = new StreamReader(_strPathXML))
{
_PublisherData = (PublisherData)x.Deserialize(reader);
_PublisherData.BuildPublisherDictionary();
iResult = _PublisherData.PublisherDictionary.Count;
}
}
catch
{
iResult = MakeResult(false);
}
}
It works. But I don't know if that is the simplest way. My problem with the above is that the list / dictionary are now detached from each other. So if I add a publisher to the dictionary it will now not be in the list.
Update 2
At the moment, after reading in the XML, if I add or remove a Publisher I am applying it to both the list and the dictionary. Unless there is a simpler way.
The serializer will only call the getter of your List and then call Add for each element it finds, providing it the instance of the type it deserialized from that element.
If your requirement is to have both a list and a dictionary you'll have to provide an implementation of an type that does so and implements an applicable interface.
The following ListDict uses a List and a Dictionary as their backing stores while implementing IList to be used in the (de)serializtion.
public class ListDict<K, T>:IList<T>
{
public Dictionary<K, T> dict = new Dictionary<K, T>();
public List<T> list = new List<T>();
Func<T,K> KeyFunc;
// takes an Function that returns a key for T
public ListDict(Func<T,K> keyfunc)
{
KeyFunc = keyfunc;
}
// called by the serializer
public void Add(T value)
{
Add( KeyFunc(value), value);
}
// fill both List and Dictionary
public void Add(K key, T value)
{
list.Add(value);
dict.Add( key , value);
}
// left out other required methods from IList<T>
}
Now your PublisherData class will change as follows to leverage above class:
[XmlRoot(ElementName = "PublisherDatabase", Namespace = "http://www.publictalksoftware.co.uk/msa")]
public class PublisherData
{
private ListDict<string, Publisher> _PublishersDictionary;
public PublisherData()
{
// provide the function to generate a key for a Publisher
_PublishersDictionary = new ListDict<string,Publisher>( (p) => p.Name );
}
[XmlElement]
public ListDict<string,Publisher> Publishers
{
get { return _PublishersDictionary; }
}
[XmlIgnore]
public Dictionary<string, Publisher> PublisherDictionary
{
get {return _PublishersDictionary.dict; }
}
}
Using above classes gives me a filled list and Dictionary directly after deserialization. You'll have to make sure of course to keep the backing stores in sync in the ListDict. Maybe you can do without it but that depends on your exact usecase.

Replace object on heap?

Maybe this is real simple or breaking all the rules or maybe I just dont know what its called so I cant find it.
Anyway, I want to be able to replace an entire object on the heap. I've added a small code sample to show what I want to do, and a way of doing it, but I just want to know if there is a more elegant way?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BasicObjectTest
{
class Program
{
static void Main(string[] args)
{
List<Test> testList = new List<Test>
{
new Test {Value=1,NiceString="First" },
new Test {Value=2,NiceString="Second" },
new Test {Value=3,NiceString="Third" }
};
var replacementTestClass = new Test { Value = 2, NiceString = "NEW" };
EasyWay(testList, replacementTestClass);
var correctTestClass = testList.FirstOrDefault(x => x.Value == 2);
Console.WriteLine(correctTestClass.NiceString); //Expecting "Forth"
Console.ReadLine();
HardWay(testList, replacementTestClass);
correctTestClass = testList.FirstOrDefault(x => x.Value == 2);
Console.WriteLine(correctTestClass.NiceString);
Console.ReadLine();
}
private static void HardWay(List<Test> testList, Test replacementTestClass)
{
//This will work!
var secondTestClass = testList.FirstOrDefault(x => x.Value == 2);
CopyPropertiesUsingPropertyInfo(secondTestClass, replacementTestClass);
}
private static void CopyPropertiesUsingPropertyInfo(Test secondTestClass, Test replacementTestClass)
{
foreach(var pi in secondTestClass.GetType().GetProperties())
{
pi.SetValue(secondTestClass, pi.GetValue(replacementTestClass, null));
}
}
private static void EasyWay(List<Test> testList, Test replacementTestClass)
{
//This wont work, but I want it to!
var secondTestClass = testList.FirstOrDefault(x => x.Value == 2);
secondTestClass = replacementTestClass;
}
}
}
and my Test object
class Test
{
public int Value { get; set; }
public string NiceString { get; set; }
}
There must be a more elegant way of doing this?
I know why the first alternative does not work: I just change the object reference for that variable.
Update:
Using this thinking I understood it for a long time I tested this now thinking it would work, but the test fails. Why? Didnt I replace the object so that every object using it should use the new object? See complete code below
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var main = new Main { Property = 1 };
var dependent = new Dependent(main);
void ChangeRef(ref Main Oldmain, Main newMain)
{
Oldmain = newMain;
}
ChangeRef(ref main, new Main { Property = 5 });
Assert.AreEqual(5,dependent.Main.Property);
}
}
public class Main
{
public int Property { get; set; }
}
public class Dependent
{
public Dependent(Main main)
{
Main = main;
}
public Main Main { get; set; }
}
There must be a more elegant way of doing this?
There is one basic thing you're missing. When you search for the object in the list, and one is found, you get back a copy of the reference pointing to that object. This means that when you alter it, you're only altering the copy. The original reference in the list is still pointing to that same old object instance.
but what if I didnt have a list. I just had the object reference in a
variable?
Then you could use the ref keyword to pass the reference type by reference:
public static void Main(string[] args)
{
var test = new Test { Value = 1, NiceString = "First" };
var newTest = new Test { Value = 2, NiceString = "AlteredTest!" };
UpdateTest(ref test, newTest);
Console.WriteLine(test.NiceString); // "AlteredTest!"
}
public static void UpdateTest(ref Test originalTest, Test other)
{
originalTest = other;
}
An alternative way to approach this is with the proverbial "extra level of indirection".
Instead of storing the objects in the list, you store wrapper objects instead. The wrapper object provides an "Item" field which points to the actual object. Then you can update the "Item" field to point it at the new object.
A simple generic wrapper class could look like this:
class Wrapper<T>
{
public T Item;
public Wrapper(T item)
{
Item = item;
}
public static implicit operator Wrapper<T>(T item)
{
return new Wrapper<T>(item);
}
}
Then you could use it like so:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Test
{
public int Value { get; set; }
public string NiceString { get; set; }
}
class Wrapper<T>
{
public T Item;
public Wrapper(T item)
{
Item = item;
}
public static implicit operator Wrapper<T>(T item)
{
return new Wrapper<T>(item);
}
}
class Program
{
static void Main(string[] args)
{
var testList = new List<Wrapper<Test>>
{
new Test {Value = 1, NiceString = "First"},
new Test {Value = 2, NiceString = "Second"},
new Test {Value = 3, NiceString = "Third"}
};
var replacementTestClass = new Test { Value = 2, NiceString = "NEW" };
EasyWay(testList, replacementTestClass);
var correctTestClass = testList.FirstOrDefault(x => x.Item.Value == 2);
Console.WriteLine(correctTestClass.Item.NiceString); //Expecting "New"
Console.ReadLine();
}
private static void EasyWay(List<Wrapper<Test>> testList, Test replacementTestClass)
{
var secondTestClass = testList.FirstOrDefault(x => x.Item.Value == 2);
secondTestClass.Item = replacementTestClass;
}
}
}

Creating a List of Lists in C#

I seem to be having some trouble wrapping my head around the idea of a Generic List of Generic Lists in C#. I think the problem stems form the use of the <T> argument, which I have no prior experience playing with. Could someone provide a short example of declaring a class which is a List, that therein contains another List, but where the type of the object contained therein is not immediately known?
I've been reading through the MS documentation on Generics, and I am not immediately sure if I can declare a List<List<T>>, nor how exactly to pass the <T> parameter to the inside list.
Edit: Adding information
Would declaring a List<List<T>> be considered legal here? In case you are wondering, I am building a class that allows me to use a ulong as the indexer, and (hopefully) steps around the nasty 2GB limit of .Net by maintaining a List of Lists.
public class DynamicList64<T>
{
private List<List<T>> data = new List<List<T>>();
private ulong capacity = 0;
private const int maxnumberOfItemsPerList = Int32.MaxValue;
public DynamicList64()
{
data = new List<List<T>>();
}
A quick example:
List<List<string>> myList = new List<List<string>>();
myList.Add(new List<string> { "a", "b" });
myList.Add(new List<string> { "c", "d", "e" });
myList.Add(new List<string> { "qwerty", "asdf", "zxcv" });
myList.Add(new List<string> { "a", "b" });
// To iterate over it.
foreach (List<string> subList in myList)
{
foreach (string item in subList)
{
Console.WriteLine(item);
}
}
Is that what you were looking for? Or are you trying to create a new class that extends List<T> that has a member that is a `List'?
or this example, just to make it more visible:
public class CustomerListList : List<CustomerList> { }
public class CustomerList : List<Customer> { }
public class Customer
{
public int ID { get; set; }
public string SomethingWithText { get; set; }
}
and you can keep it going. to the infinity and beyond !
A list of lists would essentially represent a tree structure, where each branch would constitute the same type as its parent, and its leaf nodes would represent values.
Implementation
public sealed class TreeList<T> : List<TreeList<T>>
{
public List<T> Values { get; } = new List<T>();
public TreeList<T> this[int index]
{
get
{
while (index > Count - 1)
{
Branch();
}
return base[index];
}
}
public TreeList<T> Branch()
{
TreeList<T> result = new TreeList<T>();
Add(result);
return result;
}
}
Example
internal static class Program
{
public static void Main()
{
// Create the root element...
TreeList<string> treeList = new TreeList<string>();
// You can add branches the old-fashioned way...
treeList.Add(new TreeList<string>());
// Add leaf node values to your first branch...
treeList[0].Values.Add("Hello, World!");
treeList[0].Values.Add("Goodbye, World!");
// You can create new branches from any branch like this...
// Note: You could also chain branch statements; i.e. treeList.Branch().Branch().Branch()
TreeList<string> branch2 = treeList.Branch();
// Add leaf node values to your second branch...
branch2.Values.Add("Alice");
branch2.Values.Add("Bob");
// You can also create branches until you reach the desired branch index...
// The TreeList indexer will loop until the desired index has been created, and then return it.
treeList[7].Values.Add("Alpha");
treeList[7].Values.Add("Bravo");
treeList[7].Values.Add("Charlie");
// How many branches does the root have?
Console.WriteLine($"Treelist branches: {treeList.Count}");
// What's at branch 0's values?
foreach (string value in treeList[0].Values)
{
Console.WriteLine(value);
}
// What's at branch 1's values?
foreach (string value in treeList[1].Values)
{
Console.WriteLine(value);
}
// What's at branch 7's values?
foreach (string value in treeList[7].Values)
{
Console.WriteLine(value);
}
}
}
Now, whether you should implement something like this is another matter. Extending List<T> isn't recommended: Why not inherit from List<T>?
public class ListOfLists<T> : List<List<T>>
{
}
var myList = new ListOfLists<string>();
I have the following code
public class ChildClass
{
public string FieldName { get; set; }
public string Value { get; set; }
public string StatusClass { get; set; }
public string StatusMessage { get; set; }
}
Creating a list of list obj is as follows
List<List<ChildClass>> obj = new List<List<ChildClass>>();
Look a direct example here:
public partial class Form1 : Form
{
List<List<Label>> txtList;
List<List<int>> num;
public Form1()
{
InitializeComponent();
txtList = new List< List<Label> >() {
new List<Label> { label1, label2, label3 },
new List<Label> { label4, label5, label6 },
new List<Label> { label7, label8, label9 }
};
num = new List<List<int>>() { new List<int>() { 1, 2 }, new List<int>() { 3, 4 } };
}
}
you should not use Nested List in List.
List<List<T>>
is not legal, even if T were a defined type.
https://msdn.microsoft.com/en-us/library/ms182144.aspx

Categories

Resources