C# List<T> definition in gRPC proto3 - c#

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

Related

Why can't the properties of anonymous types be swapped within arrays?

I know that in C# I can declare an array of anonymous types like this:
var anons = new[]
{
new { name = "" , something = ""},
new { name = "", something = "" }
};
I can understand that all the objects need to have the same properties, or else one won't be able to iterate through them and use those properties like:
foreach (var anon in anons)
{
Console.WriteLine(anon.name);
}
But what I don't understand is why do their properties need to have the same order?
For example, the following code won't compile:
var anons = new[]
{
new { name = "" , something = ""},
new { something = "", name = "" }
};
Why isn't this allowed, since in a normal object, the properties can be declared no matter their order, and the rest of the code could use them, as it does right now?
From the documentation for anonymous types: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/anonymous-types
If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type. They share the same compiler-generated type information.
In other words, you're creating two anonymous types and the sequence of property names and property types don't match. They look pretty much the same to us, but the compiler sees them as two different types, which means that it can't infer one type for the array declaration.
Even though the answer given by Scott is virtually correct, it does not answer the why question entirely. Since this is a question more about the compiler design regarding anonymous types array, and most of us can't come up with a clear answer, I will keep the question open and postpone accepting an answer until somebody answers the why question. Meanwhile I will leave here the following theory:
To the question
why do their properties need to have the same order?
Why not?
Since one can declare an array of anonymous types right now, having the possibility to swap the order of the properties within objects would not help anybody.
Contrarily to this, changing the order of the properties of an anonymous object within the objects of an array of anonymous types can be misleading and for the sake of consistency should be avoided. In this case, a warning or a at least a message should be displayed for the programmers who are trying to swap the properties of the objects like that so why not making it an error from the beginning and remove the need to make the C# compiler smart enough to sort out the properties itself.
In conclusion: Having the properties always in the same order is not a missing functionality, but a feature.

C# How to Access a Specific Index of a List of classes

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 ...

Removing from list recursively in C#

I have the following recursive function that is used to search down a hierarchical tree and remove found objects from a list:
private List<Tag> RemoveInvalidTags(Device device, List<Tag> tags)
{
var childDevices = device.ChildDevices.Select(c => c.ChildDevice);
foreach (var child in childDevices)
{
tags.Remove(child.Tag);
RemoveInvalidTags(child, tags);
}
return tags;
}
What I am expecting this to do is remove all child device tags at this level from the tags list, call the function recursively for your children, then return that list up to the previous level.
Will this pass the tags list by reference and modify the original passed list? Or should I be doing something along the lines of
validTags = CollectValidTags(child, tags);
and adding up all the returned lists?
Will this pass the tags list by reference
No. The list object is passed "by value" (but see next). (ref or out is required to "pass by reference" in C#, but that is not being done here, nor does it need to be.)
and modify the original passed list?
Yes. This is because the list object is passed. And that list object is mutated. Passing a reference type (anything defined with class) never implicitly makes a copy/clone/duplicate. An object is what it is.
Now, back to "pass by value": the "value passed" is the value of the "reference" (internal, no need to concern with this): this calling strategy is better known as Call/Pass By Object Sharing in a langauge like C#. The same object is shared (just as if it were assigned to two different variables). (Value types -- a struct -- are different in that they (often) are copied/duplicated on the stack, but a List<T> is a class.)
Or should I be doing something along the lines of
It depends upon the desired semantics. Is the caller expecting the side-effects directly or indirectly? Can the mutation side-effect lead to unexpected scenarios? Make sure to document it either way. (I prefer the way that guarantees the initial object is not mutated.)
Hope that clears some things up.
Happy coding.
In your code you are modifying the items in your tags parameter and passing back the modified list as your result. You want to avoid modifying lists in this way - especially inside loops where it can cause you grief in many situations.
I have a LINQ-based alternative for you.
If I understand the intent of your code you want to do something like this:
Func<Device, IEnumerable<Device>> flatten = null;
flatten = d =>
{
return (new [] { d }).Concat(
from c in d.ChildDevices
from f in flatten(c)
select f);
};
var collectedValidTags = flatten(device).Select(d => d.Tag);
var result = tags.Except(collectedValidTags).ToList();
This approach doesn't pass your list of tags around so there is no chance of modifying your original list.
Does this help?
Short answer - your code will do what you want.
Long answer - you should read descriptions of what the ref keyword does. I would suggest you read as many descriptions as possible; there are many different ways to articulate it ("I like to think of it as... ") and some will work for you whilst others won't. If you read many descriptions (from people who understand it) then some kind of understanding should gel for you.
Here's a list to get you started:
Use of 'ref' keyword in C# (my answer)
C# ref keyword usage
Passing by ref?
Example of practical of "ref" use

Is it possible to define a local struct, within a method, in C#?

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.

How can I create a sequence of numbered variables at run time?

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.

Categories