I have the following code
using System;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
List<object> list = new List<object>();
list.Add(new {
Value = 0
});
//Console.WriteLine(list[0].Value);
}
}
Is there a simple way to write the commented line of code without causing a compile time error? I know I could resort to using the dynamic keyword or implementing an extension method for the Object class that uses Reflection, but is there maybe another more acceptable way?
The goal is the avoid creating a class since its only purpose would be to store data. But at the same time still be able to retrieve the data later on in the program. This code will eventually end up in a web method which is why I want it to be dynamic / anonymous in the first place. All of the objects would end up having the same properties, as they would be storing values stored in tables, but the values are needed later for other calculations.
Is there a simple way to write the commented line of code without causing a compile time error?
Not with the way you've declared the list. If your list will contain only objects of that anonymous type, you could use an array initializer and convert it to a List<{anonymous type}>:
var list = (new [] {
new { Value = 0 }
}).ToList();
Console.WriteLine(list[0].Value);
The nice thing is that you can add to the list easily, since anonymous types with the same properties are merged into one type by the compiler:
list.Add(new {Value = 1});
Per Servy's comment, a method to avoid an array creation would just be:
public static List<T> CreateList<T>(params T[] items)
{
return new List<T>(items);
}
usage:
var list = CreateList(new { Value = 0 });
Related
I was working on something today, but I noticed something in the code, so let me explain the situation.
I get data as IEnumerable from different concreate classes of interface, look at this sample code
public interface ISampleClass {
IEnumerable<ISampleClass> GetSampleData();
}
public class SampleClassAsPerson : ISampleClass
{
public IEnumerable<ISampleClass> GetSampleData()
{
// Return data from DB
// Return list for this example
return new List<SampleClassAsPerson>() {new SampleClassAsPerson(), new SampleClassAsPerson()};
}
}
I put the data that comes from GetSampleData() method in Array of my Interface(will see this in the code bellow), I noticed that my Array not holding the same data as the variable from the same type, lets look at the code
public class TestArrayAndSingle
{
public const byte ARRAY_SIZE = 10;
public const byte FIRST_PLACE_IN_ARRAY = 0;
public static void DoTheTest()
{
// First as single element
IEnumerable<ISampleClass> singleIEnumerable = new List<ISampleClass>();
singleIEnumerable = new SampleClassAsPerson().GetSampleData(); // Works Fine for variable of type new List<ISampleClass>()
// Second as array of elements
IEnumerable<ISampleClass>[] arrayOfIEnumerable = new IEnumerable<ISampleClass>[ARRAY_SIZE];
arrayOfIEnumerable[FIRST_PLACE_IN_ARRAY] = new SampleClassAsPerson().GetSampleData(); // Works fine also
IEnumerable<ISampleClass>[] arrayOfList = new List<ISampleClass>[ARRAY_SIZE];
arrayOfList[FIRST_PLACE_IN_ARRAY] = new SampleClassAsPerson().GetSampleData(); // Return ArrayTypeMismatchException, This should be the same as singleIEnumerable I guess(new List<ISampleClass>())
}
}
So for the first one IEnumerable singleIEnumerable = new List(); works fine but in IEnumerable[] arrayOfList = new List[ARRAY_SIZE]; first item gives exception (System.ArrayTypeMismatchException - Attempted to access an element as a type incompatible with the array.).
Can anyone explain why? does element in array treated differently from same type variable?!
You have a collection of List<T> and are trying to store a more generic IEnumerable<T> in it. but not all IEnumerable<T>s are lists, so the compiler doesn't allow it. What if the IEnumerable<T> was a stack? or a linked list? or a LINQ query?
With a array of a certain type, you can store items that are of that type or more specific, but not less specific. So you can store lists in an array of enumerables (because all lists are enumerables), but not enumerables in an array of lists (since not all enumerables are lists).
I'm trying to work on a table view in Xcode and Visual studio, and am setting it up to import data, but I keep getting an error in the List.
using System.Collections.Generic;
using AppKit;
namespace HCATester
{
public class NormsLogDataSource : NSTableViewDataSource
{
public NormsLogDataSource(){}
public List Norms = new List();
public override nint GetRowCount(NSTableView tableView)
{
return Norms.Count;
}
}
}
Whenever I select it to see what's wrong, this is what I get:
Implements the System.Collections.Generic.IList interface. The size of a List is dynamically increased as required. A List is not guaranteed to be sorted. It is the programmer's responsibility to sort the List prior to performing operations (such as BinarySearch) that require a List to be sorted. Indexing operations are required to perform in constant access time; that is, O(1).
Your problem is with the declaration of your List. You are using the System.Collections.Generic namespace which (among other collections) contains the generic List<T>. But you aren't specifying the generic type parameter.
You see, before we had generics, we used ArrayList which just held a collection of objects, so we'd always need to cast it to what we actually wanted. For example, if we want a ArrayList of integers we could declare our list like this:
ArrayList list = new ArrayList();
list.Add(1);
list.Add(2);
list.Add(3);
But when using it we would need to cast our item from object to whatever type we wanted like so:
int item1 = (int) list[0];
int item2 = (int) list[1];
// ...
This gets confusing and error prone, for example if a Method takes an ArrayList as a parameter you'd always need to make sure every element of said ArrayList was of the right type.
In come Generics and the generic List<T>, with it we can define a strongly typed List. The same example as above but using List is much easier to read and understand:
List<int> list = new List<int>();
list.Add(1);
list.Add(1);
list.Add(1);
int item1 = list[0];
int item2 = list[1];
// ...
Now we don't need to cast our object, as we already know what datatype it is. This also adds a lot more security, as we can define what types are valid inside a List.
Now to answer your question, you need to specify the datatype you are using, you said string so I'll show you how. All you need to do is replace your line where you are declaring the List with this:
public List<string> Norms = new List<string>();
P.S the generic () part of a class can be read as "of" or "for", e.g List<T> would be read as "A List of T", List<int> would be "A List of Integers". And ViewModel<TView> would be read as "A ViewModel for TView"
I'm learning the power of generics in C# in conjunction with NHibernate. I'd like to attempt the following in the pasted code.
In an attempt to do some post processing of N number of NHibernate objects I worked on a utility method leveraging generics to make it applicable to all NHibernate mapping classes we use now, or in the future. It works but I need to hard code each call for each mapping class. This is a pain and will need continuing updating as our schema and mappings change over time.
I do have an ever up-to-date list of all mapping classes by string name through the NHibernate mappings I generate on the fly. If there was a way to use this list of string names to call my generics based method, I'd be super happy.
Can anyone tell me if this is possible? Do I need to find another route?
Thanks so much in advance!!!
public static void ProcessSomeItems()
{
// *************************************************************
// As of now I have to list all classes as such to be processed
// It works but I have to update manually when new mapping classes are created
// *************************************************************
NHibDoSomethingUtil<AspnetMembership>();
NHibDoSomethingUtil<AspnetProfile>();
NHibDoSomethingUtil<AspnetRole>();
NHibDoSomethingUtil<AspnetUser>();
// and so forth...
// I have a up-to-date list of all mappings from "HbmMapping" and can get a list of all in the
// list form as below
List<string> mappingNames = new List<string>();
foreach (string mappingName in mappingNames)
{
Type theType = Type.GetType(mappingName);
// I know I'm getting Types and Generics classes and so forth all jumbled but
// how in the heck would I do something like the below?
NHibDoSomethingUtil<theType>(); // Obviously doesn't compile ;-)
}
}
// Generic method
public static void NHibDoSomethingUtil<T>() where T : class
{
using (ISession session = sourceDBSessionFactory.OpenSession())
{
foreach (dynamic item in new List<T>(session.QueryOver<T>().List()))
{
// Process item;
}
}
}
ecsousa gave great input and I was able to accomplish what I needed with something like the following.
foreach (HbmClass mappingClass in mapping.Items)
{
Console.WriteLine(" -- Discovered Mapping: " + mappingClass.Name);
Type mappingClassType = Type.GetType(mappingClass.Name);
var genericMethod = typeof(Migration).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(mappingClassType);
method.Invoke(null, null);
}
You will need to use Reflection in order to accomplish this. Instead of directly calling NHibDoSomethingUtil, try this:
var genericMethod = typeof(TheClassName).GetMethod("NHibDoSomethingUtil");
var method = genericMethod.MakeGenericMethod(theType);
method.Invoke(null, null);
Note that you have to replace TheClassName by the class containing both methods.
Keep in mind the this kind of code is slow, and you should use it very carefully.
How would I pass a list of values into a function, where the values are already stored in a list and the function isn't the same every time?
To explain, I've got a list of several different types of custom objects (A List<object> to make this work) and I want to pass those objects into a function. However, the function isn't always the same. I could have several different functions, and, assuming that List's contents will always match the function's input variables, I want to be able to pass the list's contents into my function.
The following code is an example of what might work, but for one flaw:
List<object> myListOfVariables = new List<object>();
myListOfVariables.Add("Hello, world!");
myListOfVariables.Add(10);
void SayHelloXTimes(string helloString, int x) {
for(int i = 0;i<x;i++) {
print(helloString)
}
}
SayHelloXTimes(myListOfVariables[0], myListOfVariables[1]);
Now, since I know my list will always contain the right amount of variables in the right positions, that would work, if I only had one function. But the problem is, I need to expand this so I could take apart my list and pass it into functions with different amounts of parameters.
For other reasons, I know my list will always have the right amount of variables in the right positions, so we don't need to worry about that. I'll also know the name of the function I need to pass my values into. I suppose I could do a load of if statements depending on the length of my list, like this:
if (myListOfVariables.Length == 2) {
SayHelloXTimes(myListOfVariables[0], myListOfVariables[1]);
}
else if (myListOfVariables.Length == 3) {
SayHelloXTimesForY(myListOfVariables[0], myListOfVariables[1], myListOfVariables[2]);
}
However, this (obviously) is really clunky code and I'd like to avoid it at all costs. Is there another solution to my problem? I know this is really confusing, but I did my best to explain it. If you're still confused as to what I'm trying to do, please let me know.
And no, this is not a homework problem. ;)
I think want you want to do can be done using reflection. Look at MethodBase.Invoke Method
All you have to do is add all the parameters in the order the function expects to an object array.
class Program
{
public static void SayHelloXTimes(string helloString, int x)
{
for (int i = 0; i < x; i++)
{
Console.WriteLine(helloString);
}
}
static void Main(string[] args)
{
MethodInfo Method = typeof(Program).GetMethod("SayHelloXTimes");
Method.Invoke(null, new object[] { "foo", 3 });
Console.ReadLine();
}
}
You want params:
void SayHelloXTimes(params string[] list) {
for(int i = 0;i<list.Length;i++) {
print(list[i])
}
}
SayHelloXTimes("Hi", "Hi", "Hi"); // legal
SayHelloXTimes("Hi"); // legal
SayHelloXTimes("Hi", "Hi", "Hi", "Hi", "Hi", "Hi"); // still legal
If this were my application, I would create a parameter class to hold the list values.
You could pass the list into the class' constructor and either extract it into class-local properties (since you know the positions) or you could expose the values as readonly property directly from the list.
You can then just pass an instance of the parameter class to each of the methods and not have to worry about the number of parameters to the methods.
I have a project which stores values in SQL and later retrieves them for analysis. To keep track of what kinds of values might be stored, I created a class roughly like this:
private class DataField
{
public string FieldName;
public string FieldType;
}
When values are being read for analysis, a switch statement is used as follows (simplified):
switch (DataField.FieldType)
{
case "int":
List<int> InputData = new List<int>();
// Populate list from DB
break;
case "bool":
List<bool> InputData = new List<bool>();
// Populate list from DB
break;
}
Rather than maintain code in multiple places, I am looking for a way to get rid of the switch statement, but that means I need to dynamically create collections based on the type. Current that type is (naively?) a string, but I think I could improve this by changing the class:
private class ImprovedDataField
{
public string FieldName;
public Type FieldType;
}
And then dynamically create collections somehow:
Type DataType = typeof(DataField.FieldType);
List<DataType> InputData = new List<DataType>();
// Populate list from DB
This of course does not work, resulting in a Type or namespace name expected error.
Unfortunately I'm not very familiar with working with the Type class, nor generics nor anonymous types as I search for a solution (nothing seems to be appropriate).
How can I reduce duplication of code where the only difference in each switch statement branch is the type of variable collection being produced?
If you want to create statically-typed collection of objects of type known at runtime, you need to use reflection. See i.e. this blog entry - that's the solution for creating List<T>:
public static IList CreateGenericList(Type collectionType)
{
var listType = typeof(List<>).MakeGenericType(new[] { collectionType});
return (IList) Activator.CreateInstance(listType);
}
So in your example:
Type dataType = DataField.FieldType;
IList inputData = CreateGenericList(dataType);
// Populate list from DB
Why do you need a typed collection? Why not to use an ArrayList?
ArrayList list = new ArrayList()
list.Add( /* value read from database */ )