Is there a way to dynamically name variables?
What I need to do is take a list of variable names from an input file and create variables with those names. Is this possible?
Something like:
Variable <dynamic name of variable here> = new Variable(input);
Assume that I already have the Variable class taken care of, and the name of the variable is contain in a string called strLine.
Use a Dictionary<string, Variable>.
e.g.
var vartable = new Dictionary<string, Variable>();
vartable[strLine] = new Variable(input);
C# 4.0, using the dynamic objects:
dynamic d = new ExpandoObject();
((IDictionary<string, object>)d)["MyProperty"] = 5;
int val = d.MyProperty; // 5
No, but you could use a Dictionary<string, Variable>, and then you can refer to each variable by its quoted name.
You can't do that, but what you're looking to do is begging for a Dictionary use:
Dictionary<object, object> d = new Dictionary<string, object>();
d.Add("Variable1", value1);
d.Add("Variable2", value2);
d.Add("Variable3", value3);
try this one,user json to serialize and deserialize:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Script.Serialization;
namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
object newobj = new object();
for (int i = 0; i < 10; i++)
{
List<int> temp = new List<int>();
temp.Add(i);
temp.Add(i + 1);
newobj = newobj.AddNewField("item_" + i.ToString(), temp.ToArray());
}
}
}
public static class DynamicExtention
{
public static object AddNewField(this object obj, string key, object value)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string data = js.Serialize(obj);
string newPrametr = "\"" + key + "\":" + js.Serialize(value);
if (data.Length == 2)
{
data = data.Insert(1, newPrametr);
}
else
{
data = data.Insert(data.Length-1, ","+newPrametr);
}
return js.DeserializeObject(data);
}
}
}
Variable names should be known at compile time. If you intend to populate those names dynamically at runtime you could use a List<T>.
var variables = List<Variable>();
variables.Add(new Variable { Name = input1 });
variables.Add(new Variable { Name = input2 });
...
No. You can load them into a Dictionary object, however. This allows you to still reference them (somewhat) using a name, which is a bit easier than using an Index, as you would with an Array or ArrayList.
I would use some sort of keyed collection, like a hashtable, dictionary, or list of structures with the name. You can then refer to the variable by name:
var value = variableDictionary["MyVariableName"];
var value = variableHashtable["MyVariableName"];
var value = variableList.First(x=>x.Name == "MyVariableName");
There is no other way to dynamically "name" a variable.
No. Use an array, otherwise you can't do this.
Related
This question already has answers here:
How do I check for null or empty string for many arguments? - C#
(5 answers)
Closed 2 years ago.
Variables:
private string filePath1 = null;
private string filePath2 = null;
private string filePath3 = null;
private string filePath4 = null;
private string filePath5 = null;
private string filePath6 = null;
private string filePath7 = null;
private string filePath8 = null;
private string filePath9 = null;
private string filePath10 = null;
Current If statement
if (string.IsNullOrEmpty(filePath1))
{
errors.Add("File Not Attached");
}
if (string.IsNullOrEmpty(filePath2))
{
errors.Add("File Not Attached");
}
....
Question:
Instead of having multiple if statements, for each variable. How can I create 1 if statement to go through all these variables?
Something like this:
if (string.IsNullOrEmpty(filePath + range(1 to 10))
{
errors.Add("File Not Attached");
}
You can achieve this using Reflection. This is obviously discouraged for this scenario, as the other answers provide better solutions, just wanted to show you it's doable the way you intended it to be done (which doesn't mean it's the correct way)
public class Test
{
private string filePath1 = null;
private string filePath2 = null;
private string filePath3 = null;
}
Usage:
Test obj = new Test();
//loop through the private fields of our class
foreach (var fld in obj.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(x => x.Name.StartsWith("filePath"))) // filter
{
if (string.IsNullOrEmpty(fld.GetValue(obj) as string))
{
errors.Add("File Not Attached in variable: " + fld.Name);
}
}
In nearly all cases where you're using variables with a differently numbered suffix, you should really be using a collection (array, list, ...). This is one of those cases. I'll be using a list for this answer but any collection will suffice.
private List<string> filePaths = new List<string>()
{
"path1",
"path2",
"path3",
"path4"
};
You can then use a loop to iterate over your list:
foreach (string path in filePaths)
{
if(String.IsNullOrEmpty(path))
errors.Add("File not attached");
}
Create a new arraylist, add all file paths to it (or initialise it with all filepaths) and the loop over the elements in the array (using for-each loop). For each element, check if nullOrEmpty and if yes add to your errors string.
ArrayList arrlist = new ArrayList();
arrList.add(filePath1);
arrList.add(filePath2);
arrList.add(filePath3);
arrList.add(filePath4);
arrList.add(filePath5);
arrList.add(filePath6);
arrList.add(filePath7);
arrList.add(filePath8);
arrList.add(filePath9);
arrList.add(filePath10);
foreach (string element in arrList)
{
if (string.IsNullOrEmpty(element)
{
errors.Add("File Not Attached");
}
}
ps. You might want to print a new line after each error:
errors.Add("File Not Attached\n");
// Create list
List<string> filePaths = new List<string>;
//Add path in list like
filePaths.add(filePath1);
//Check for null path here
foreach (string filepath in filePaths)
{
if (string.IsNullOrEmpty(filepath)
{
errors.Add("File Not Attached");
}
}
In order to treat all strings the same way they have to be in some collection.
using System.Linq;
...
string[] allPaths = new string[10];
// Do something with these ten paths...
if (allPaths.Any(x => string.IsNullOrEmpty(x))
errors.Add("File Not Attached");
As stated every other answers, you should use a collection.
If you really want to stick with fields names, you can use reflection, but I strongly recommend to use collections over reflection :
// using System.Reflection;
// Below code is meant to be used in a method of the class that holds the fields.
for (int i = 1; i <= 10; i++)
{
if (string.IsNullOrEmpty(this.GetType()
.GetField($"filePath{i}",
BindingFlags.NonPublic | BindingFlags.Instance)?
.GetValue(this))
{
errors.Add("File Not Attached");
}
}
If you can make those variable class fields i would vote for Innat3's Answer.
Bu if this is not possible and you can't make those variables class fields then i suggest to you do like following :
class Program
{
static void Main(string[] args)
{
Dictionary<string, int> names = new Dictionary<string,int>();
for (int i = 0; i < 10; i++)
{
names.Add(String.Format("name{0}", i.ToString()), i);
}
var xx1 = names["name1"];
var xx2 = names["name2"];
var xx3 = names["name3"];
}
}
Because in c# we can't compute dynamically variable names.
Hope this helps.
Apologizes if the title doesn't make much sense, English isn't my native language.
What I am trying to do:
1. I have a list of strings
2. I want to check each of those strings against another list of strings
3. Depending which string they contain, the output will be different
In code, it looks like this:
public static Hashtable Matches = new Hashtable
{
{"first_match", "One"},
{"second_match", "Two"},
{"third_match", "Three"},
{"fourth_match", "Four!"},
{"fifth_match", "Five"}
};
Now, I have a list of strings like this:
001_first_match
010_second_match
011_third_match
And I want to check if each string in the list exists in the hashtable (or maybe other data type appropriate for this situation, suggestions appreciated) and based on that, to take the value for the key.
For example: 001_first_match is in the hashtable with first_match key. If found, then I want to take the One value of it and use it.
I can't use ContainsKey because the list of strings isn't 100% exact as the keys. The key is contained within the string, but there's extra data in the string.
I hope it's not too confusing what I want to do.
Try following linq :
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication58
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string[] inputs = { "001_first_match", "010_second_match", "011_third_match" };
foreach (string input in inputs)
{
var results = Matches.Keys.Cast<string>().Where(x => input.Contains(x)).FirstOrDefault();
Console.WriteLine("Input '{0}' found in HashTable : {1}", input, (results == null) ? "False" : "True, key = '" + results + "', Value = '" + Matches[results] + "'");
}
Console.ReadLine();
}
public static Hashtable Matches = new Hashtable
{
{"first_match", "One"},
{"second_match", "Two"},
{"third_match", "Three"},
{"fourth_match", "Four!"},
{"fifth_match", "Five"}
};
}
}
You can use Linq to do this by enumerating over the hashtable, casting each item to DictionaryEntry, and seeing if any element of the list of strings contains the key from the hashtable:
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace Demo
{
class Program
{
public static void Main(string[] args)
{
var Matches = new Hashtable
{
{"first_match", "One"},
{"second_match", "Two"},
{"third_match", "Three"},
{"fourth_match", "Four!"},
{"fifth_match", "Five"}
};
var Targets = new List<string>
{
"001_first_match",
"010_second_match",
"011_third_match"
};
var matches =
Matches.Cast<DictionaryEntry>()
.Where(x => Targets.Any(s => s.Contains((string)x.Key)))
.Select(v => v.Value);
Console.WriteLine(string.Join("\n", matches)); // Outputs "Three", "One" and "Two".
}
}
}
using System;
using NUnit.Framework;
using System.Collections.Generic;
namespace StackOverflow
{
public class StringMatch
{
public Dictionary<string, string> Matches = new Dictionary<string, string>
{
{ "first_match", "One" },
{ "second_match", "Two" },
{ "third_match", "Three" },
{ "fourth_match", "Four!" },
{ "fifth_match", "Five" }
};
public List<string> Strings = new List<string>
{
"001_first_match",
"010_second_match",
"011_third_match"
};
[Test]
public void FindMatches()
{
foreach (var item in Strings)
{
foreach (var match in Matches)
{
if (item.Contains(match.Key))
{
Console.WriteLine(match.Value);
break;
}
}
}
}
}
}
I can do this by two dimensional array hope it can help you.
public string test()
{
string result="";
string[,] Hashtable = new string[2,2]
{
{"first_match", "One"},
{"second_match", "Two"},
};
string match = "001_first_match";
for (int i = 0; i < Hashtable.GetLength(0); i++)
{
string test1= Hashtable[i, 0];
if (match.Contains(test1)) { result = Hashtable[i, 1]; }
}
return result;
}
I want to dynamically create instances of a class, so I created a dictionary of objects of that class and assign the names by appending a counter to a string. But how do I access the properties of the objects?
The code is something like this:
int count = 0;
string name = "MyInstanceName" + count.ToString();
Dictionary<string, MyClass> d = new Dictionary<string, MyClass>();
d.Add(name, new MyClass(Parameter));
//try to retrieve the Property - this doesn't work
textBox1.Text = d[name.Property];
You can do this
int count = 0;
string name = "MyInstanceName" + count.ToString();
var d = new Dictionary<string, MyClass>();
d.Add(name, new MyClass());
textBox1.Text = d[name].Property;
You created a Dictionary that the key is a string and the value is a instance of MyClass.
When using Dictionary index, the value between brackets [] should be the key, in this case a string.
myDictionary["keyValue"]
textBox1.Text = d[name].Property;
in addition to Alberto Monteiro's answer, don't forget to cast your object:
textBox1.Text = (myClass) d["MyInstanceName1"].Property;
or
var myInstanceX = d["MyInstanceName1"].Property;
textBox1.Text = myInstanceX.myStringProperty();
In C# (unlike VB), you don't need to specify the type of a variable if the compiler can determine it elsewhere, so you can also simplify:
Dictionary<string, MyClass> d = new Dictionary<string, MyClass>();
into
var d = new Dictionary<string, MyClass>();
var is a typed variable declarator (unlike javascript)
Let’s say list of member names stored in an array like below,
string[] myMembers = { "ChapterName", "Medium", "LastName", "OrderID" };
I wrote the following code to generate dynamic class and members along with random values.
var myDynamicClassList = new List<ExpandoObject>();
foreach (var MemberName in myMembers)
{
dynamic dynamicClass = new ExpandoObject();
dynamicClass.MemberName = new Random().Next();
myDynamicClassList.Add(dynamicClass);
}
In order to display output of the above myDynamicClassList I wrote the following code.
foreach (var x in myDynamicClassList)
{
foreach (var property in (IDictionary<String, Object>)x)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
Showing output like this
MemberName : 123465461
MemberName : 564613611
MemberName : 134654321
MemberName : 786451214
But Instead of above output I am expecting the output like below
ChapterName : 123465461
Medium : 564613611
LastName : 134654321
OrderID : 786451214
Here is my question, is it possible to add dynamic member name to a dynamic class in c#. If it is possible please let me know, if not please guide me to complete this job.
I really appreciate your help in advanced.
As described in a similar question ("Dynamically adding properties to an ExpandoObject"), you can do this by using IDictionary directly:
string[] myMembers = { "ChapterName", "Medium", "LastName", "OrderID" };
var myDynamicClassList = new List<ExpandoObject>();
Random random = new Random();
foreach (var MemberName in myMembers)
{
IDictionary<string, object> dynamicClass = (IDictionary<string, object>)(new ExpandoObject());
dynamicClass.Add(MemberName, random.Next());
myDynamicClassList.Add((ExpandoObject)dynamicClass);
}
foreach (var x in myDynamicClassList)
{
foreach (var property in (IDictionary<String, Object>)x)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
}
However, you should be aware of possible known memory limitations with this method as described in the comments of the post linked above, or in the Microsoft issue. I would possibly rethink the design to consider what properties are actually needed, or simply using a Dictionary if it's feasible (to avoid the dynamic ExpandoObject entirely).
I also moved your Random outside of the loop. Creating new instances of Random inside a loop may not give you the results you expect...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Collections;
using System.IO;
namespace Deligate
{
class Program
{
public static List<Employee> empList = new List<Employee>();
public static void UserInfo(int val)
{
Employee emp = new Employee();
Console.WriteLine($"Enter {val+1} Employee Details :- ");
Console.WriteLine("Enter Your Name: ");
emp.Name= Console.ReadLine();
Console.WriteLine("Enter your Email: ");
emp.Email = Console.ReadLine();
Console.WriteLine("Enter Mobile Number");
emp.Mobile = Console.ReadLine();
empList.Add(emp);
}
public static void CountEmp()
{
Console.WriteLine("How many user you want to add:");
var UserCount = int.Parse(Console.ReadLine());
for (int i = 0; i < UserCount; i++)
{
UserInfo(i);
}
foreach (var employee in empList) {
Console.WriteLine(employee.Name+ ", " + employee.Email+", "+employee.Mobile);
}
System.IO.File.Delete(#"D:\Compare.txt");
foreach (var el in empList)
{
System.IO.File.AppendAllText(#"D:\Compare.txt", el.Name+", "+el.Email+", "+el.Mobile + Environment.NewLine);
}
}
public static void Main(string[] args)
{
CountEmp();
Console.ReadKey();
}
}
}
How do I do this dynamically using DelimitedClassBuilder so that the columns in the file can expand but not break my program?
[DelimitedRecord(",")]
public class MyRecord
{
public string Name;
[FieldOptional, FieldArrayLength(0, 100)]
public string[] I_DONT_CARE_WHAT_COMES_AFTER_THIS;
}
i.e. how do I finish this:
var cb = new DelimitedClassBuilder("xyz", ",");
cb.AddField("Name", "string");
... how do I add the array field here?
Type type = cb.CreateRecordClass();
var engine = new DelimitedFileEngine(type);
Good question. The best I can find is:
var cb = new DelimitedClassBuilder("xyz", ",");
cb.AddField("Name", "string");
cb.AddFields(100);
foreach (var field in cb.Fields.Where(f => f.FieldName.StartsWith("Field")))
{
field.FieldOptional = true;
}
var type = cb.CreateRecordClass();
var engine = new DelimitedFileEngine(type);
I can't get it to work with
cb.AddField("I_DONT_CARE", typeof(string[]));
Nor with
cb.AddField("I_DONT_CARE", typeof(string[]).FullName);
both of which ought to work.