C# referring to object variable with string - c#

Hi in Actionscript I may refer to a variable within an object thusly
objectName["variableName"] = "Some value";
How would I do the equivalent in c#
thanks

Dictionary is not part of the language & is provided in the framework.
Use Dictionary<Key, Value>.
e.g.
Dictionary<string, string> myData = new Dictionary<string, string>();
myData.Add("first", "stack");
myData.Add("second", "overflow");
Console.WriteLine(myData["first"]);

It depends.
If you genuinely mean an object you want:
objectName.variableName = "Some value";
If you want a Map (also known as an associative array) your best solution is a Dictionary:
Dictionary<string, string> d = new Dictionary<string, string>()
d["variableName"] = "Some value";

You could use a dictionary...
using System.Collections.Generic;
public class x{
public method1() {
var objectName = new Dictionary<string, object>();
objectName["variableName"] = "Some value";
}
}
Or, use strongly-typed properties (safer and fast running), recommended where you know variable names at compile-time.
public class Person{
public string Name {get;set;}
public int Age {get;set;}
}
// and use it as follows in your functions
var person1 = new Person() {
Name = "Fred",
Age = 21,
};
// again, to demonstrate different syntax to do same thing
var person2 = new Person();
person2.Name = "Danny";
person2.Age = 2;
person2.Age = "x"; // won't compile - expects int, hence safer

What type of variable? It sounds like a dictionary/hashtable is most suited. These have index operators [], so the syntax will be identical.

C# doesn't have "objects with variables". C# objects have properties which are accessed like MyObject.PropertyName.

What you're referring to is a key-value collection. A Dictionary is C# implementation of this. Note that a dictionary only allows for unique keys. You can use it generically so you can use it like this.
Dictionary<string, string> myValues = new Dictionary<string, string>();
myValues.Add("variableName", "variableValue");
or
Dictionary<string, int> familySizes = new Dictionary<string, int>();
familySizes.Add("simpsons", 5);
As you can see you can choose what datatypes you use.

Related

define a List like List<int,string>?

I need a two column list like:
List<int,string> mylist= new List<int,string>();
it says
using the generic type System.collection.generic.List<T> requires 1 type arguments.
Depending on your needs, you have a few options here.
If you don't need to do key/value lookups and want to stick with a List<>, you can make use of Tuple<int, string>:
List<Tuple<int, string>> mylist = new List<Tuple<int, string>>();
// add an item
mylist.Add(new Tuple<int, string>(someInt, someString));
If you do want key/value lookups, you could move towards a Dictionary<int, string>:
Dictionary<int, string> mydict = new Dictionary<int, string>();
// add an item
mydict.Add(someInt, someString);
You could use an immutable struct
public struct Data
{
public Data(int intValue, string strValue)
{
IntegerData = intValue;
StringData = strValue;
}
public int IntegerData { get; private set; }
public string StringData { get; private set; }
}
var list = new List<Data>();
Or a KeyValuePair<int, string>
using Data = System.Collections.Generic.KeyValuePair<int, string>
...
var list = new List<Data>();
list.Add(new Data(12345, "56789"));
With the new ValueTuple from C# 7 (VS 2017 and above), there is a new solution:
List<(int,string)> mylist= new List<(int,string)>();
Which creates a list of ValueTuple type. If you're targeting .NET Framework 4.7+ or .NET/.NET Core, it's native, otherwise you have to get the ValueTuple package from nuget.
It's a struct opposing to Tuple, which is a class. It also has the advantage over the Tuple class that you could create a named tuple, like this:
var mylist = new List<(int myInt, string myString)>();
That way you can access like mylist[0].myInt and mylist[0].myString
Since your example uses a generic List, I assume you don't need an index or unique constraint on your data. A List may contain duplicate values. If you want to insure a unique key, consider using a Dictionary<TKey, TValue>().
var list = new List<Tuple<int,string>>();
list.Add(Tuple.Create(1, "Andy"));
list.Add(Tuple.Create(1, "John"));
list.Add(Tuple.Create(3, "Sally"));
foreach (var item in list)
{
Console.WriteLine(item.Item1.ToString());
Console.WriteLine(item.Item2);
}
Use C# Dictionary datastructure it good for you...
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("one", 1);
dict.Add("two", 2);
You can retrieve data from Ditionary in a simple way..
foreach (KeyValuePair<string, int> pair in dict)
{
MessageBox.Show(pair.Key.ToString ()+ " - " + pair.Value.ToString () );
}
For more example using C# Dictionary... C# Dictionary
Navi.
Not sure about your specific scenario, but you have three options:
1.) use Dictionary<..,..>
2.) create a wrapper class around your values and then you can use List
3.) use Tuple
List<Tuple<string, DateTime, string>> mylist = new List<Tuple<string, DateTime,string>>();
mylist.Add(new Tuple<string, DateTime, string>(Datei_Info.Dateiname, Datei_Info.Datum, Datei_Info.Größe));
for (int i = 0; i < mylist.Count; i++)
{
Console.WriteLine(mylist[i]);
}
For that, you could use a Dictionary where the int is the key.
new Dictionary<int, string>();
If you really want to use a list, it could be a List<Tuple<int,string>>() but, Tuple class is readonly, so you have to recreate the instance to modifie it.

Nested Dictionary collection in .NET

The .NET Dictionary<TKey, TValue> object allows assignment of key/values like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["1"] = "foo";
dict["2"] = "bar";
but I cannot use a Dictionary like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["F1"]["F2"]["F3"] = "foo";
dict["2"]["X"] = "bar";
Is there a collection in .NET which allows me to nest [], or would I have to create my own?
If I have to create my own, how would I do this?
EDIT:
It would also be useful if I could have implementations which expect unique keys, like so:
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result is "bar" because "foo" was overridden
and an implementation where a key can be used more than once
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result can be "foo" and "bar"
Is this possible?
EDIT (as per Jon Skeet's question):
I want to use the structure like so (as a very rough example):
json["data"]["request"]["name"] = "username";
json["data"]["request"]["pass"] = "password";
resolves to
{ data: { request: { name: "username", pass: "password" } } }
and equally there would be an equivalent for XML etc.
Having a requirement for arbitrarily long nesting, I have come up with the following solution, which as far as I can see, doesn't break, according to my test:
public class NestedDictionary<K, V> : Dictionary<K, NestedDictionary<K, V>>
{
public V Value { set; get; }
public new NestedDictionary<K, V> this[K key]
{
set { base[key] = value; }
get
{
if (!base.Keys.Contains<K>(key))
{
base[key] = new NestedDictionary<K, V>();
}
return base[key];
}
}
}
TEST:
NestedDictionary<string, string> dict = new NestedDictionary<string, string>();
dict["one"].Value = "Nest level 1";
dict["one"]["two"]["three"].Value = "Nest level 3";
dict["FieldA"]["FieldB"].Value = "Hello World";
Console.WriteLine(dict["one"].Value);
Console.WriteLine(dict["one"]["two"]["three"].Value);
Console.WriteLine(dict["FieldA"]["FieldB"].Value);
You can do this using the standard Dictionary, you just have to declare the nesting:
Dictionary<string, Dictionary<string, string>> dict = ...
string test = dict["first"]["second"]
Dictionary<string, Dictionary<string, Dictionary<string, string>>> dict = ...
string test = dict["first"]["second"]["third"]
etc
The original Dictionary COM object which was created to work with vb6 would respond to an attempt to access a non-existent item by creating a new item of type Dictionary with the corresponding name. This approach allows something to be stored to MyDict["Foo"]["Bar"] without having to first create MyDict["Foo"]. The problem with this approach is that while one would want to add "Foo" to MyDict when performing a write to MyDict["Foo"]["Bar"], one would rather not create such an item if one was attempting to e.g. evaluate MyDict["Foo"]["Bar"].ValueOrDefault(someDefaultValue).
I've used such collections, since they can be handy for modeling certain things (conceptually they're a lot like XML documents). One workable approach is to declare that dictionaries which contain nothing but other dictionaries are considered semantically as non-entities which may be removed at any opportunity. When implicitly adding a subcollection, set a flag in the item to which it's added it indicating that it should be checked for items that may be deleted (or keep a counter of how many such items may exist). Then with some reasonable frequency, scan through the dictionaries and remove such "dead" items.
An alternative approach is to have the indexer from the dictionary not return an actual item, but instead return an "ephemeral indexer" type, which keeps a reference to the parent object and has internal methods GetNestedForReading, SetNestedForReading, GetValue, and SetValue, which chain back to it. Then a statement Foo["Bar"]["Boz"] = "George"; will end up effectively performing Foo.SetNestedForReading("Bar").SetValue("Boz", "George"); while z = Foo["Bar"]["Boz"]; will effectively perform Foo.GetNestedForReading("Bar").GetValue("Boz");. Calling SetNestedForReading method with a non-existent key will create and return a new nested item; the GetNestedForReading method will an immutable "empty" item. Using this approach will thus avoid creating empty items.
Although the latter approach is more complicated than the former, it has another advantage. It's possible to have each node to individually hold its collection as either a shared deeply-immutable dictionary or an unshared mutable one; if a GetNestedForWriting call sees that the nested object is immutable, it can construct a new shallowly-mutable object holding the same items. If one defines the cloning method for a mutable node as creating a new immutable node with (immutable) clones of all subnodes, and the cloning method of an immutable node as returning itself, cloning trees that are mostly immutable becomes very cheap. If one had a newly-cloned (thus immutable) four-level tree with sixteen items on each level (65,536 leaf nodes total) and all the nodes were shared-immutable, updating a leaf node would only require replacing one leaf and four other nodes with mutable ones. Cloning the tree again would only require creating new immutable objects for the nodes which had been replaced with mutable ones (e.g. copying five things). Although one would have the convenience of a fully-mutable tree, one would have the efficiency advantages of an immutable one.
The biggest "problem" I see with this approach is that to avoid some weird behaviors one must require the use of syntax like MyDict["Foo"]["Bar"].Value = "George". If implicit conversion operators were used to avoid that requirement, someone would expect a statement like var st = MyThing["Foo"]["Bar"]; to define st as a string snapshot of whatever MyThing["Foo"]["Bar"] holds at that moment; instead it would define it as something that will index MyThing["Foo"]["Bar"]. If one had to use .Value to read or write strings from such a type, the fact that the variable wasn't a string would be apparent. If one used implicit operators to allow such assignments, the behavior would be odd. It's too bad there's no way a function can specify "do not allow this return value to be used for type inference".
Incidentally, it's possible to have the indexer type be a class or a generic struct. If it's a class, an access to foo["Bar"]["boz"]["baz"]... nested N deep would likely require the creation of N temporary heap objects. If it's a generic struct, it would entail the creation of N structs, but the more-deeply-nested structs would get bigger. For reasonable levels of nesting, generic structs would probably be slightly more efficient, but classes would probably be easier to work with.
You have to decide on either supporting a fixed number of string keys to look up, or provide a more general key mechanism if the number of keys can vary. For the first case try the following:
Dictionary<string,Dictionary<string,string>> dict =
Dictionary<string,Dictionary<string,string>>();
dict["F1"]["F2"] = "foo";
Dictionary<string,Dictionary<string,Dictionary<string,string>>> dict2 =
Dictionary<string,Dictionary<string,string>>();
dict2["F1"]["F2"]["F3"] = "bar";
For the second case, you could do the following:
Dictionary<string[],string> dict = new Dictionary<string[],string>(new MyEqualityComparer());
dict[new string[] {"F1","F2"}] = "foo";
dict[new string[] {"F1","F2","F3"}] = "bar";
where the class MyEqualityComparer would be something like:
public class MyEqualityComparer : IEqualityComparer<string[]>
{
public int GetHashCode(string[]item)
{
int hashcode = 0;
foreach (string s in item)
{
hashcode |= s.GetHashCode();
}
return hashcode;
}
public bool Equals(string [] a, string [] b)
{
if (a.Length != b.Length)
return false;
for (int i = 0; i < a.Length; ++i)
{
if (a[i] != b[i])
return false;
}
return true;
}
Use a Dictionary as TValue:
var dict2 = new Dictionary<string, Dictionary<string, string>>();
var dict3 = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
for example:
var dict =
new Dictionary<string, Dictionary<string, string>>
{
{
"F1", new Dictionary<string, string>
{
{"F2", "foo"}
}
}
};
dict["F1"]["F2"] = "bar";
I think, your case is good place to use DynamicObject. I'll create an example for json using Dictionary<string, object> internally.
Same idea can be used for xml also.
string json = #"{""Name"":""Joe"",
""Age"":30,
""Address"":{ ""City"":""NY"" }}";
dynamic dynObj = new DynamicJson(json);
Console.WriteLine(dynObj.Name);
Console.WriteLine(dynObj.Age);
Console.WriteLine(dynObj.Address.City);
--
public class DynamicJson : DynamicObject
{
Dictionary<string, object> _Dict;
public DynamicJson(string json)
{
_Dict = (Dictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json);
}
DynamicJson(Dictionary<string, object> dict)
{
_Dict = dict;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
object obj;
if (!_Dict.TryGetValue(binder.Name, out obj)) return false;
if (obj is Dictionary<string, object>)
{
result = new DynamicJson((Dictionary<string, object>)obj);
}else
{
result = obj;
}
return true;
}
}

C# .NET Generate once a string array which his indexes are string values from a table

I have a table contains the columns Title and Info.
I would like to create an array it's index will be the Title, and actual value of the array in that index is the Info in the same row.
So if I have 3 Rows like that:
Title Info
ABC Hi
DEF Sup
GHI Hello
I would like to ask for StringArray["ABC"], and this will return "Hi".
How can I do that?
Thanks Guy
You want a Dictionary<String, String>, not a string array.
var myStrings = new Dictionary<String, String>();
myStrings.Add("ABC", "Hi");
myStrings.Add("DEF", "Sup");
myStrings.Add("GHI", "Hello");
Console.WriteLine(myStrings["ABC"]);
Arrays can only be indexed with an integer. You would have to use Dictionary<string, string>, or some other type that implements IDictionary<string, string>, or you could implement your own type with a string indexer.
Please refer to Dictionary for that
You can do in this way
Dictionary<string, string> Book = new Dictionary<string, string>();
Book.Add("ABC","Hi");
Book.Add("DEF","Sup");
Book.Add("GHI","Hello");
so on and so forth.
So then when you say
Book["ABC"] it will return Hi
You should use dictionary to implement it.
var table = new Dictionary<string,string>(
{"ABC", "Hi"},
{"DEF", "Sup"},
{"GHI", "Hello"}
);
now you can use it
var info = table["ABC"];
you should be careful an exception will be thrown if you use unexisted key
you can use TryGetValue to avoid this exception
string info;
if(!table.TryGetValue("ABC", out info))
{
info = "default value if required";
}

How to create an array with label and not integer

Suppose I have an array of strings like :
myArray["hello", "my", "name", "is", "marco"]
to access to this variable, I have to put an integer as index. So if I wanto to extract the third element I just do :
myArray[2]
Now, I'd like to use label instead of integer.
So for example somethings like :
myArray["canada"]="hello";
myArray["america"]="my";
myArray["brazil"]="name";
myArray["gosaldo"]="is";
myArray["italy"]="marco";
How can I do this on C#? Is it possible? Thanks
That's called an associative array, and C# doesn't support them directly. However, you can achieve exactly the same the effect with a Dictionary<TKey, TValue>. You can add values with the Add method (which will throw an exception if you try to add an already existing key), or with the indexer directly, as below (this will overwrite the existing value if you use the same key twice).
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["canada"] = "hello";
dict["america"] = "my";
dict["brazil"] = "name";
dict["gosaldo"] = "is";
dict["italy"] = "marco";
C# has a Dictionary class (and interface) to deal with this sort of storage. For example:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict.Add("canada", "hello");
dict.Add("america", "my");
dict.Add("brazil", "name");
dict.Add("gosaldo", "is");
Here are the docs: http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
With a Dictionary you will be able to set the "key" for each item as a string, and and give them string "values". For example:
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("canada", "hello");
You're looking for an associative array and I think this question is what you're looking for.

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;
}
}

Categories