What are alternatives to declaring data structure in functions? - c#

Is there a good existing or upcoming alternative in C# to declaring data structures in methods? It's possible to use anonymous types, but there are difficulties with declaring them. Let's say I have a hypothetical class:
class ThingsManager
{
private void DoThings(IEnumerable<Thing> things)
{
var thingLocations = new Dictionary<string, string>();
foreach(var thing in things)
{
// some complicated logic and checks for current thing;
// if current thing satisfies all conditions:
var thingName = thing.Name;
var thingLocation = location; // taken somewhere from upper lines
thingLocations.Add(thingName, thingLocation);
}
// ... later
foreach(var thingLocation in thingLocations)
{
// here I don't know what is the key and what does the value mean.
// I could use Linq and anonymous types, but sometimes it is clearer
// to use foreach if the logic is complicated
}
}
}
Now, what I'd like to see:
class ThingsManager
{
private void DoThings(IEnumerable<Thing> things)
{
struct ThingLocations
{
string ThingName {get;set;}
string Location {get;set;}
}
var thingLocations = new List<ThingLocations>();
foreach(var thing in things)
{
// some complicated logic and checks for current thing;
// if current thing satisfies all conditions:
var thingName = thing.Name;
var thingLocation = location; // taken somewhere from upper lines
thingLocations.Add(new ThingLocation(thingName, thingLocation));
}
// ... later
foreach(var thingLocation in thingLocations)
{
// now here I can use thingLocation.ThingName
// or thingLocation.Location
}
}
}
I could also declare the structure in the class, but it doesn't make sense to use it anywhere except in my function. It would be better if my function were the only place where I could use this data structure. I'm looking for a better way to handle such situations, or at least be able to declare anonymous types.

Anonymous types would help with the naming aspect, but you would have to translate the input into your anonymous type and the type would remain internal to the method scope.
// Assumes thingLocation comes from somewhere...
var thingLocations = things
.Select(t => new { ThingName = t.Name, Location = new ThingLocation(t.Name, thingLocation) } );
It is done using the Select extension method in order to project to an anonymous type.
You can declare anonymous types without linq, but you will find it annoying trying to add those to lists / dictionaries:
var me = new { Name = "Adam", Age = 27 };
I'm going on record to say that I wouldn't take this approach, personally I'd either use anonymous types, a Tuple<string, string>, or a custom type.
Failing all of that, and if you don't mind firing up the DLR, you could use an ExpandoObject:
class Thing
{
public string Name;
}
static void Main(string[] args)
{
var things = new List<Thing>() { new Thing { Name = "Adam" } };
var thingLocations = new List<dynamic>();
foreach (var thing in things)
{
dynamic location = new ExpandoObject();
location.Name = thing.Name;
location.Location = "here";
thingLocations.Add(location);
}
// ... later
foreach(var thingLocation in thingLocations)
{
Console.WriteLine(thingLocation.Name);
Console.WriteLine(thingLocation.Location);
}
Console.ReadLine();
}
This allows you to dynamically add properties as you need them by declaring them on the spot. You can then use these later because ExpandoObject provides the plumbing to the DLR when the DLR asks for a member by name.

C# does indeed support Anonymous Types, but the real answer is:
No, you can't do that in C#. Just declare the struct as private right above your method and forget about it.

Related

How to compare list of anonymous object with Enum in c#

I am forming List of object as below, Control is List of Enum.
Ex:
public enum Controls
{
Undefined = 0,
[EnumReferenceTypeField(DisplayName = "Edit")]
Edit = 1,
[EnumReferenceTypeField(DisplayName = "Save")]
Save = 2,
}
Constructing actions List is already written code, am not allowed to change.
var actions = new List<object>();
foreach (var control in Controls)
{
actions.Add(new
{
c = (int)control ,
t = control.ToString()
});
}
and checking the condition as below,
if (actions.Exists(a => a == (object)Enums.Controls.Save))
actions.Remove(Enums.Controls.Submit);
Even if i convert Enum to object type the Exists condition not satisfying, even though actions list have Save action. If i mouse over action at runtime it has to values "2" and "Save". i want to check Save is exists and perform some logic.
There are various things wrong here:
If Controls truly is an enum as you have shown, then you cannot enumerate it with
foreach (var control in Controls) // won't work if Controls is an enum type
You can instead use something like:
var controls =
Enum
.GetValues(typeof(Controls))
.Cast<Controls>()
.ToList();
foreach (var control in controls)
...
Since actions is a List<object>, and the items you are adding to it are of anonymous type, you cannot access the members of the items. Either actions must be implicitly typed:
var actions =
controls // as above
.Select(control => new {
c = (int)control ,
t = control.ToString()
}).ToList();
or you need to use a non-anonymous type and cast to it:
class MyAction {
public int c { get; set; }
public string t { get; set; }
public MyAction(Controls control) {
c = (int)control;
t = control.ToString();
}
}
var actions = new List<MyAction>();
foreach (var control in controls)
actions.Add(new MyAction(control));
If Controls is defined how you say, there is no such value as Controls.Submit.
If Controls really is an enum, then it does not make any sense to have a line like:
if (actions.Exists(a => a == (object)Enums.Controls.Save))
because the members of Controls are static and known at compile time. You should be able to reason about them yourself.
More than likely, the code you have posted is incomplete or incorrect in a critical way.
After some analysis I have tried myself and below code is working perfectly.
Created anonymous object from enum like below,
object saveAction= new
{
c = (int)Enums.Controls.Save,
t = Enums.Controls.Save.ToString()
};
object submitAction = new
{
c = (int)Enums.Controls.Submit,
t = Enums.Controls.Submit.ToString()
};
if (actions.Exists(a => a.Equals(saveAction)))
{
actions.Remove(submitAction);
}
Equals only working not "==". Refer below link
http://www.informit.com/articles/article.aspx?p=1237024&seqNum=4

How to get Neo4JClient to perform a bulk insert

When running the following code I receive an exception "CypherTypeException: Collections containing mixed types can not be stored in properties." - What am I doing wrong, and what needs to change to make it work?
var wordObjs = new List<object>();
foreach (string word in WordGroups.GetAllWords())
{
wordObjs.Add(new { Value = word});
}
GraphClient.Cypher
.Create("(word:Word {words})")
.WithParam("words", new { words = wordObjs})
.ExecuteWithoutResults();
One solution would be use a concrete class
private class Value {
public string Value {get;set;}
}
and use new List<Value>() instead, I think the client is having trouble with the anonymous nature of your List.

Linq anonymous properties over parameter

Is it possible select an anonymous type via list of properties as parameter. The method should look like:
public void TestLinq(List<"Properties"> properties, List<Data> data)
{
var dat = from d in data select new { properties };
}
I know the description sounds clumsy but I hope I get some help.
It would be important to know the term I have to look for this topic.
You can use the Dynamic LINQ query library (download the sample) to create the list of properties in your projection, like so:
public dynamic TestLinq(IEnumerable<Data> data, IEnumerable<string> properties)
{
// Validate parameters.
if (properties == null) throw new ArgumentNullException("properties");
if (data == null) throw new ArgumentNullException("data");
// Construct the field list.
var fields = new StringBuilder();
foreach (string p in properties) fields.AppendFormat("{0},", property);
// Throw an exception if there are no items.
if (fields.Length == 0) throw new ArgumentException(
"The properties enumeration contains no elements.", "properties");
// Remove the last comma.
fields.Length--;
// Select the items and return. Create the
// projection here.
return data.Select("new(" + fields + ")");
}
Note that the return type is of type dynamic, so you'll have no compile-time checking, and unless you're duck-typing, you probably won't have much knowledge of the fields.
You might be better off creating strong types for this, depending on your needs (if this is based on user-input, then you can't obviously).
Here you go, this is based on this answer https://stackoverflow.com/a/5310828/491950
List<string> properties = new List<string>() { {"ResultPrefix"}, {"ProfileResult"}};
foreach (dynamic d in ListProperties(properties, cellValues))
{
Console.WriteLine(d.ResultPrefix);
}
public static List<dynamic> ListProperties(List<string> properties, List<ChemistryResult> chemistryResults)
{
List<dynamic> output = new List<dynamic>();
foreach (ChemistryResult chemistryResult in chemistryResults)
{
IDictionary<string, Object> result = new ExpandoObject();
foreach (string property in properties)
{
PropertyInfo propertyInfo = typeof(ChemistryResult).GetProperty(property);
result[property] = propertyInfo.GetValue(chemistryResult);
}
output.Add(result);
}
return output;
}
You cannot use anonymous types in a method signature. It cannot be used as a parameter or the return type.
What you could do, is declare the parameter as dynamic, but dynamic can get really sticky, so I recommend avoiding it. You could have a List<dynamic> parameter, then you will be able to access members of the type, but you will not get type checking at compile time.
Another option it to use IEnumerable or IList. Using either of these will allow you to access the members of the collection without knowing the type. This is safer, as you have all of your compile time checks, but will not allow you to access members or the anonymous type.
But really, you should just convert your anonymous type into a real class so you can make your life easier.
I am sorry for the confusion. The outcome should be a csv that's right. The user should be able to define the order of the columns. But for me it was very difficult to formulate a good question. I am looking for a solution with expresisons not with reflection. My Idea was to generate a List of anonymous objects (with the right order) and out of them I wanted to create the csv. So I know the following is working:
public void Get(List<Value> data,Expression<Func<Value, T>> converter)
{
var dat = from d in data
select
new
{
converter
};
}
Is it possible to safe the Expression> converter in a property and combine many of them to one? So I would get the corret order

C# properties as array notation

Using JavaScript it's possible to access an object using the dot notation or array notation.
var myArray = {e1:"elem1",e2:"elem2",e3:"elem3",e4:"elem4"};
var val1 = myArray["e1"];
var val2 = myArray.e1;
Is it possible to accomplish this using C#?
This is what I have attempted:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, FormCollection frmVals)
{
string value;
Owner owner = new Owner();
foreach (var key in frmVals.AllKeys)
{
value = frmVals[key];
owner[key] = value;
}
}
While there is no way to do this exactly with C#. You could change your code in several ways that may accomplish your goal. First, you could use a Dictionary like this:
var something = new Dictionary<string, object>() {
{ "property", "value"},
{ "property1", 1}
};
foreach (var keyVal in something) {
var property = keyVal.Key;
var propertyValue = keyVal.Value;
}
Another option would be to do it dynamically:
dynamic somethingDyn = new System.Dynamic.ExpandoObject();
somethingDyn.property = "value";
somethingDyn.property1 = 1;
var somethingDynDict = (IDictionary<string, object>)somethingDyn;
var propValue = somethingDyn["property"];
foreach (var keyVal in somethingDynDict) {
var property = keyVal.Key;
var propertyValue = keyVal.Value;
}
If you need to iterate through properties on a strongly typed object you could use reflection:
var owner = new Metis.Domain.User();
var properties = owner.GetType().GetProperties();
foreach (var prop in properties) {
object value = prop.GetValue(owner, null);
}
I wouldn't recommend this, but you could put an indexer in your class, accepting a string, then use reflection to read that property. Something like:
public object this[string key]
{
get
{
var prop = typeof(ThisClassName).GetProperty(key);
if (prop != null)
{
return prop.GetValue(this, null);
}
return null;
}
set
{
var prop = typeof(ThisClassName).GetProperty(key);
if (prop != null)
{
prop.SetValue(this, value, null);
}
}
}
Javascript array notation is not something you can use in C#.
You need to use dot notation to access members of an object.
You will need to access each value directly and assign it:
owner.key = frmVals[key];
owner.key2 = frmVals[key2];
There are workarounds - using dictionaries, dynamic objects or even reflection, but the scenario is not a directly supported by C#.
There is no syntactic equivalent possible in C# but there are some ways to approximate the same feature.
You could mimic the indexer type access using a Dictionary but then you'd lose the property-style access. For property-style access, you could do something similar in C# by using an anonymous type, as in:
var myType = new { e1="elem1",e2="elem2",e3="elem3",e4="elem4"};
var val1 = myType.e1;
However, that doesn't create an array or allow array type access and it doesn't allow for modifications to the type after creation.
To get a closer approximation to the JavaScript feature, you may be able to use ExpandoObject to mimic this a little more closely, or you could implement something yourself.
For that, you'd need a class that has a constructor to auto-generate properties from the passed in array and exposes an indexer, which in turn uses reflection to find the named property.
Initialization of this type would be something like:
var myType = new MyType(new[]{
{"e1", "elem1"},
{"e2", "elem2"},
{"e3", "elem3"},
{"e4", "elem4"}});
This assumes there is a sub-type for each element definition (possibly using Tuple or KeyValuePair. The constructor would then be taking an IEnumerable<T> of that type.
Yes, it's possible.
There are two possibilities:
1) The list of keys and values is dynamic.
The array notation is provided by e.g. System.Collections.Generic.Dictionary<string, blah>
The member access notation can be provided through DLR magic and the dynamic keyword.
2) The list of keys and values is static.
Member access notation is already provided by the C# compiler.
Array notation can be had using Reflection (hopefully with a cache to improve performance).
In the static case, member access notation is MUCH faster. In the dynamic case, array notation will be a little faster.

Declaration of Anonymous types List [duplicate]

This question already has answers here:
A generic list of anonymous class
(22 answers)
Closed 8 years ago.
Is there any way to declare a list object of anonymous type. I mean
List<var> someVariable = new List<var>();
someVariable.Add(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
This is because I need to create a collection at runtime.
How about dynamic?
List<dynamic> dynamicList = new List<dynamic>();
dynamicList.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
It involves a bit of hackery but it can be done.
static List<T> CreateListFromSingle<T>(T value) {
var list = new List<T>();
list.Add(value);
return list;
}
var list = CreateListFromSingle(
new{Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}}
);
You can make a list like this, but you'll again have to use some serious hackery, and you'll have to use some "type by example" situations. For example:
// create the first list by using a specific "template" type.
var list = new [] { new { Name="", Phones=new[] { "" } } }.ToList();
// clear the list. The first element was just an example.
list.Clear();
// start adding "actual" values.
list.Add(new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } });
In general you can use the (arguably bad-smelling) cast by example trick others have mentioned to create instances of any generic type parameterized with an anonymous type for the type argument. However, for List<T> there is a slightly less gross way to do it:
var array = new[] {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
var list = array.ToList();
Your sketch of a proposed syntax is similar to a feature we did not implement for C# 3 or 4, but we considered. We call the feature "mumble types", and it would go something like this:
List<?> myList = new List<?>() {
new {
Name="Krishna",
Phones = new[] {"555-555-5555", "666-666-6666"}
}
};
We call it "mumble types" because of course you'd read it "myList is a new list of hrmmf". :-)
The idea is that the compiler would look at the initializers and do its best to figure out what the type could possibly be, just the same way as how "var" means "look at the initializer and figure out what the type of the variable is". Whether we'd use "var" as the "mumble" or "?" (which is similar to what Java does in a related feature), or something else is an open question.
In any event, I wouldn't hold my breath waiting for this feature if I were you. It hasn't made the cut for several language versions so far, but it will stay on the list of possibilities for a while longer I think. If, hypothetically speaking, we were to be designing future versions of the language. Which we might or might not be. Remember, Eric's musings about future versions of C# are for entertainment purposes only.
Here's an approach that is somewhat cleaner than many of the other suggestions:
var list = Enumerable.Repeat(new { Name = "", Phones = new[] { "" } }, 0)
.ToList();
// ...
list.Add(new { Name = "Krishna",
Phones = new[] { "555-555-5555", "666-666-6666" } });
You can't make a collection of an anonymous type like this.
If you need to do this, you'll need to either use List<object>, or make a custom class or struct for your type.
Edit:
I'll rephrase this:
Although, technically, it's possible to make a list of an anonymous type, I would strongly recommend never doing this. There is pretty much always a better approach, as doing this is just making code that is nearly unmaintainable. I highly recommend making a custom type to hold your values instead of using anonymous types.
A custom type will have all of the same capabilities (since anonymous types are defined, by the compiler, at compile time), but will be much more understandable by the developer who follows you...
And just to play, too, here's my entry for "code I'd never actually want to use in the real world":
var customer = new { Name = "Krishna", Phones = new[] { "555-555-5555", "666-666-6666" } };
var someVariable = new[]{1}.Select(i => customer).ToList();
I spent quite a lot of time trying to find a way to save myself some time using a list of anonymous types, then realised it was probably quicker just to use a private class inside the current class...
private class Lookup {
public int Index;
public string DocType;
public string Text;
}
private void MyMethod() {
List<Lookup> all_lookups = new List<Lookup> {
new Lookup() {Index=4, DocType="SuperView", Text="SuperView XML File"},
new Lookup() {Index=2, DocType="Word", Text="Microsoft Word Document"}
};
// Use my all_lookups variable here...
}
I don't think this is possible. Maybe in C# 4 using the dynamic keyword?

Categories

Resources