Friends, I must create a series of ArrayLists, each containing objects of unknown origin, with each instance assigned to a separate local variable.
So far, so good... But I also need each local variable's name to follow a very specific pattern: the name should begin with "oArr", followed by one or more digits reflecting that particular array's position within the sequence. Furthermore, I will not know at compile-time how many of these arrays - and hence, how many local variables - I will be needing!
It strikes me that this is perhaps a problem that could be solved by the availability of dynamic types in C# 4.0, however I am not at all familiar with their use. How might I take code like this...
int i=0;
foreach(something)
{
ArrayList oArr+i=new ArrayList();
i++;
}
...and turn it into something that matches the criteria outlined above and actually compiles?
Alternately, is there a more simple, sane approach to this problem?
You cannot change the name of a variable during execution, since the code (even c# code) was compiled with a certain variable name. If you could change the name during execution then it would cause problems.
For example, if the language allowed to change variable names then when you try to access a variable named 'var1' the compiler has no idea if during execution that variable name changed and now is called 'x'.
Something you could try to do is to allow your program to dynamically compile some code but this is probably not the right solution to your problem. If you explain better what you need then we could provide you with an effective solution.
Hope this helped
EDIT: Seeing your editions I can tell you that it is impossible with the approach you are currently using. I could suggest you the following:
int i = 0;
List<ArrayList> masterList = new List<ArrayList>();
foreach (something)
{
masterList.Add(new ArrayList());
i++;
}
If what you need is to have each ArrayList to have a specific name you can recall you can use a dictionary:
int i = 0;
Dictionary<string, ArrayList> masterList = new Dictionary<string, ArrayList>();
foreach (something)
{
masterList.Add("oArr" + i.ToString(), new ArrayList());
i++;
}
ArrayList al = masterList["oArr1"];
Would this work for you?
var arrayLists = new List<ArrayList>();
var i = 0;
foreach(var item in list)
{
arrayLists.Add(new ArrayList());
i++;
}
Then you can access each array list by index.
Use a List of ArrayLists.
Related
Like title says, whats is definition of List is for gRPC proto3, tried to search in https://developers.google.com/protocol-buffers/docs/proto3 and found "repeated" type, but seems its read only, map is not solution, since I dont use index keys. What I need gRPC solution for List Thanks.
Although the property for the repeated field in the generated code is read-only, it's still mutable. Just add to the existing RepeatedField<T> rather than assigning a new value. Note that RepeatedField<T>.Add is overloaded so you can add a whole sequence in one call, even in a collection initializer, e.g.
string[] allNames = ...;
var message = new MyMessage
{
Names = { allNames.Where(n => n.Length > 5) }
};
I have created a class called studentRecord, and it contains several properties such as Student Number, First Name, Last Name, Courses, and Credit Hours for keeping track of individual student records. I also have created a list called List<studentRecord> lstRecords = new List<studentRecord>(); that stores the various objects (students).
I understand adding a student object through using lstRecords.Add();, but am running in to trouble with editing the objects. The user is supposed to be able to enter a student number, and then be able to access and edit the properties of that specific instance of the object. I have come up with this code:
StudentRecord editRecord = lstRecords.Find(indexRecord =>
indexRecord.intStudentNumber == intChosenRecord);
(By the way, intChosenRecord is a variable I declared to keep track of which index they are looking for)
I understand that StudentRecord is declaring a new object of that type, and that editRecord is my new object's name. However, I run into problems with using the .Find() method. I realize that .Find() searches through the list to find something that matches up with in input. Therefore, I assume that the intChosenRecord is what the program is searching for.
However, I have no idea what indexRecord is! This is the only time that it is used within the code, and I can change it to any name I want without errors. Could someone explain what this code does, and what indexRecord is?
"indexRecord" is a variable which correspond to each student in the list.
"Find" stops and returns the current student once condition (or "predicate") at the right of "=>" is true.
Therefore you can name it as you want, as long as you use the same name at left and right of "=>"
A similar loop could be :
StudentRecord editRecord = null;
foreach(var indexRecord in lstRecords)
{
if(indexRecord.intStudentNumber == intChosenRecord))
{
editRecord = indexRecord;
break; // Exits the loop.
}
}
This code is not very clean, but I give it for the sake of clarity, since it does the same than yours with an "oldschool" loop, which is certainly more familiar for you.
See http://msdn.microsoft.com/fr-fr/library/bb397687.aspx for more details on this syntax.
And http://msdn.microsoft.com/fr-fr/library/bb397926.aspx for other methods than "Find".
indexRecord is the argument of the lambda expression. It can have any name you want. In your case, it represent a StudentRecord (an element of your list)
you can easily change your code by :
StudentRecord editRecord = lstRecords.Find(x => x.intStudentNumber == intChosenRecord);
You can learn more about lambda expression on many site, as http://www.dotnetperls.com/lambda
The variable editRecord refers to the match returned by Find(), so it's not creating a new object or new instance of anything; it's referring to an existing instance.
Think of indexRecord as an identifier used to iterate over all the items in a collection, like when you say:
var numbers = new List<int>();
foreach (var n in numbers)
{
// do something with n
}
You can replace n, or indexRecord, with any identifier you like.
When you are using "=>", you are using a lambda expression.
In your case, "indexRecord" is the variable name of the input parameter for your lambda expression "indexRecord.intStudentNumber == intChosenRecord". And indexRecord correspond to a student stored in your list.
I would suggest that you get familiar with the lambda expressions, because it is a powerful and common used feature of c#.
try this ..
List<int> idlist=lstRecords.select(t=>t.intStudentNumber).toList();
int index=idlist.indexof(intChosenRecord);
studentRecord record=lstRecords[index];
i always use this ...
I wanted to know how to apply a constructor on each element of an array that would then return an array of constructed objects. Specifically, I am working with C#'s TreeNode.
The concept I want is as follows:
string[] animals = {"dog","cat","mouse"};
TreeNode[] animalNodes = TreeNode[](animals);
Where TreeNode[](animals) would have the cumulative effect of
animalNodes[0] = TreeNode("dog");
animalNodes[1] = TreeNode("cat");
animalNodes[2] = TreeNode("mouse");
I know I can us foreach and load such a structure manually but if possible, I'm looking for the elegant 'one line' way. I have looked long and hard for how to do this but could not find anything.
Some LINQ will do the trick:
TreeNode[] animalNodes = animals.Select(a => new TreeNode(a)).ToArray();
The Select extension method executes the specified delegate (specified via a lambda here) on each member of the list, and creates a list of the results (IEnumerable<TreeNode> in this case). The ToArray extension method is then used to create an array from the result.
Alternatively, you can use LINQ's query syntax:
TreeNode[] animalNodes = (from a in animals select new TreeNode(a)).ToArray();
The code generated by the compiler is the same for both these examples.
This is a different syntax that will give the same result like the other correct answer you already got.
TreeNode[] animalNodes = (from animal in animals select new TreeNode(animal)).ToArray();
While the other answers may work, I propose the following alternative.
My main reason for doing so is that the other examples require you to actually make the code look a little bit more complicated, and it's clear that you're looking to clean up your code, and make the assignment look and be more simple. This solution will also help you if you're going to be creating these TreeNodes in different places in your app (the other solutions would require you to copy and paste the assignment code to each place you're creating the TreeNode arrays.
The cost of having your assignment code cleaner, is moving the mess somewhere else (but honestly not really much of a mess, since it's all really straight-forward)
First, create a class to build the TreeNode array for you
public static class TreeNodeBuilder
{
public static TreeNode[] FromStringArray(String[] array)
{
TreeNode[] returnValue = new TreeNode[array.Length];
for(int i = 0; i < array.Length; i++)
{
returnValue[i] = new TreeNode(array[i]);
}
return returnValue;
}
}
And then in your assignment code, you can use the following:
String[] animals = {"dog", "cat", "mouse"};
TreeNode[] animalNodes = TreeNodeBuilder.FromStringArray(animals);
Conclusion
This (IMHO) is a better option than using LINQ as the other answers provide, mostly for code clarity, maintainability, and the separation you can achieve by putting all of this logic in a different file (a file like TreeNodeBuilder.cs).
For what it is worth you could also use the LINQ code provided in the other answers inside the above FromStringArray function (if you wanted to get the best of both worlds).
Anyways, my two cents :) Hope you find it helpful.
I am reading connection strings from my App.config file and for that i have following code.
try
{
string[] dbnames;
int counter = 0;
foreach (ConnectionStringSettings connSettings in ConfigurationManager.ConnectionStrings)
{
dbnames[counter] = connSettings.Name;
counter++;
}
return dbnames;
}
catch
{
throw;
}
this code giving me error use of unassigned local variable for dbnames. i will have multiple connection strings in my App.config. They can be none,1,2 and so on. Depending on the needs. so i cant statically assign the dbname size. Because there can be a scenario if they exceed the value of assigned size. eg. if i assign it a size of 5, and what if i get 6th connection string. and if i have 1, then remaining 4 will be a memory wastage.
If i am wrong then let me know.
Thanks.
Use this while initializing the array.
string[] dbnames = new string[ConfigurationManager.ConnectionStrings.Count];
OR use List<string>
You can't resize a System.Array dynamically like that.
Fortunately, there's no reason to do so. Use a different type of collection, like a List<T> instead. (Make sure you've added a using declaration for the System.Collections.Generic namespace!)
Like an array, a List<T> allows you to access the elements in the list by index, but it's also dynamically resizable at run-time, which fulfills the requirements in your question. And of course, since it's a generic method, it has the additional advantage (as compared to some of your other choices) of being strongly-typed. Since you're working with string types, you would use List<string>.
EDIT: There's absolutely no need for that empty try/catch block. Why catch an exception if you're just going to immediately rethow it? Just let it bubble up. In general, you shouldn't catch exceptions unless and only unless you can fix their immediate cause.
You're declaring dbnames as a string array, but not defining it's size.
You'll need something like:
string[] dbames = new string[4];
where "4" is the length of your array.
If, however, you need a variable length you should use List<string>. In this case you can then add to it as necessary.
As others have said, you could just use a List<string>. I would use LINQ to do all of this though, if you're using .NET 3.5 or higher:
return ConfigurationManager.ConnectionStrings
.Cast<ConnectionStringSettings>()
.Select(setting => setting.Name)
.ToArray(); // Or ToList
No need for a foreach loop (in your code - obviously it's there somewher :)
You can easily decide whether to return a list, an array, or simply IEnumerable<string>
No need for try/catch
declare it after class
e.g
i am also writing code and i used to always encounter this problem
public class ABC{
string[] array;
ABC()
{
}
//your_function_logics
}
One of the common programming best practices is "define variables as close to where they are used as possible".
I use structs frequently to create code thats almost self documenting in places. However, C# forces me to define the struct outside the method. This breaks the aforementioned best practice - its basically creating an unwanted global variable type for the entire class.
Is it possible to define a local struct inside a method, just like a local variable, and if not, could you give me a window into the reasons the C# designers decided to prevent this?
Use Case
I'm converting part of a spreadsheet into C# code. I'd like to use local structs within the method to store temporary information in an organized manner, without having to resort to hundreds of separate variables that are global in scope.
Update 2016-August: C# 7.0 may have this feature!
As of 2016-Aug, apparently, this will be a feature in C# 7.0.
So the C# compiler team agreed - wow!
Update 2020-July: Now supported by C# and C++
C++ has always fully supported this. And it's fantastic.
C# 7.0 now has value tuples for a lightweight data structure with named fields. See answer from Ghost4Man.
I believe it's not permitted to define named types within a method. As to why, I'll have to speculate. If a type is not going to be used outside, then its existence probably cannot be justified.
You can however define anonymous type variables within a method. It will somewhat resembles structures. A compromise.
public void SomeMethod ()
{
var anonymousTypeVar = new { x = 5, y = 10 };
}
It is a little late but this is my solution for lists - using anonymous vars as the structs inside of methods:
var list = new[] { new { sn = "a1", sd = "b1" } }.ToList(); // declaring structure
list.Clear(); // clearing dummy element
list.Add(new { sn="a", sd="b"}); // adding real element
foreach (var leaf in list) if (leaf.sn == "a") break; // using it
Anonymous elements (sn and sd) are somehow read only.
Since C# 7.0, you can use value tuples if you want a lightweight data structure with named fields. They can be used not only locally inside methods, but also in parameters, returns, properties, fields, etc. You can use local functions to somewhat emulate struct methods.
var book = (id: 65, pageCount: 535); // Initialization A
(int id, int pageCount) book2 = (44, 100); // Initialization B
Console.WriteLine($"Book {book.id} has {book.pageCount} pages.");
(int id, int pageCount) = book; // Deconstruction into variables
Console.WriteLine($"Book {id} has {pageCount} pages.");
Here book is of type System.ValueTuple<int, int> (a generic struct).
You could do something like this using anonymous types. MSDN examples below:
var v = new { Amount = 108, Message = "Hello" };
or
var productQuery =
from prod in products
select new { prod.Color, prod.Price };
foreach (var v in productQuery)
{
Console.WriteLine("Color={0}, Price={1}", v.Color, v.Price);
}
Nowadays, you could also use a named tuple: https://learn.microsoft.com/en-us/dotnet/csharp/tuples
No, this is not possible. If you are using .net 4.0, you could use Tuple<T1, ..., Tn> to replicate such a thing.
I don't see the reason why you would need such a struct - just use variables with speaking names and this shouldn't be any problem at all. In combination with explicit declaration using the class names there is very little space for ambiguity.
You can define an anonymous type within your method and use it. The anonymous type will be readonly, so it gets you the immutability that is desired of structs. It will not explicitly be a struct, but it will be fully defined and contained within your method.
var myLocalType = new
{
SomeValue = "Foo",
SomeId = 14
};
it's not a struct, but mayme a var can help you out here?
var person = new {Name= "John", City = "London"};
it's strong typed so it will be compile time checked
You can create a dynamic type in c# 4.0 to accomplish this task, but its not exactly what you are looking for.
However I believe that the maximum of defining variables as close to where they are used is meant to mean where a variable is introduced into program flow not where the type is declared. I believe that most types have some ability to be reused creating in method types limits you ability to create reusable blocks of code that operates on common data.