Associate variable to a list [duplicate] - c#

This question already has answers here:
Interesting "params of ref" feature, any workarounds?
(5 answers)
Closed 7 years ago.
I'm not sure if this is easy possible in C#. But I would like to get to know how this could be done easily.
public partial class Form1
{
// I left out the unimportant code for this example
private myControl cLeft,cTop,cBottom,cRight;
private List<myControl>mControls;
public Form1()
{
InitializeComponents();
//this list should contain the fields cLeft,cTop,cBottom,cRight...
mControls=new List<myControl>(){cLeft,cTop,cBottom,cRight};
/* now I want that cLeft and so on get assigned...
of course, this doesn't work because the list refers to the values of
cLeft ... which are null. So I would need to store a reference to those fields to get this work.*/
mControls.ForEach(x=>x=new myControl(this));
}
}
I'm sure it could be done through reflection, but I assume that there should be a way to do this easily in C# or isn't it possible?

It's just a simple loop, there is no need to use LINQ. You just need a for loop.
for (int i = 0 ; i < mControls.Count ; i++) {
mControl[i] = new myControl(this);
}
But, there is no need to write cLeft, cTop etc. You can just refer to them using the indexer: mControls[0], mControl[1] etc.
And remember, the foreach loop or the ForEach extension method doesn't work. This is because you are changing the reference of the variable. That is just another confusing (for beginners) feature of reference types!
Consider this method
public void ChangeReference (string s) {
s = "Hello";
}
And you call this method:
String s = "xxx";
ChangeReference (s);
Will s be "Hello" after the call? No. In the method, you are changing the location of the string in memory, but the argument is still in the same place!

Related

Is it possible to add methods into variables [duplicate]

This question already has answers here:
Easiest way to extend a Struct (PointF)
(3 answers)
Extension methods versus inheritance
(9 answers)
Extend an existing struct in C# to add operators
(7 answers)
A way to extend existing class without creating new class in c#
(3 answers)
Closed 1 year ago.
Is it possible to add methods into variables, example being.
public static int BoolToInt(bool entry)
{
if(entry == true) { return 1; }
else { return 0; }
}
bool example = checkbox1.Checked;
RandomMethod(example.BoolToInt());
Looking into minimizing visual clutter and help readability (I find RandomMethod(example.BoolToInt(), example2.BoolToInt()); easier to read than RandomMethod(BoolToInt(example), BoolToInt(example2));) I was wondering if this was possible, upon research I found this Can you assign a function to a variable in C#? which feels like it's the right direction, but it makes the variable become the method, when I want to just add into it. I'm a newbie so I couldn't go from there to what I want nor know if it's theres a way to do it, also couldn't find much reading the Microsoft Docs.
You can use C# extension methods to "extend" exists types by declaring new methods for the extended type.
static class BoolExtensions {
public static int ToInt(this bool value) {
return value ? 1 : 0;
}
}
Then you can use as:
var example = true;
var exampleAsInt = example.ToInt();
Reference:
Extension methods

Lists getting cleared unexpectedly after assignment [duplicate]

This question already has answers here:
How do I clone a generic list in C#?
(29 answers)
C# Value and Reference types
(6 answers)
Closed 4 years ago.
class ListHolder
{
public List<char> List;
public ListHolder(List<char> l)
{
this.List = l;
}
}
class Program
{
static void Main(string[] args)
{
List<char> a = new List<char>();
a.Add('s');
ListHolder c = new ListHolder(a);
a.Clear();
Console.WriteLine(c.List.Count);
}
}
I've put some list into that class, than I cleared the list and wrote the count of the list in the class... I would expect that the output should be "1" (as the list in the class contains the letter 's') but instead it writes "0". How is possible, that a.Clear clears even the list in the class? How can I achieve clearing only the list in the Main and the list in the class letting be?
Since you are passing a reference instead of the list itself, you will get 0 after clearing your list.
What you have to do is passing to the class a new List containing the other list's values:
cl c = new cl(new List<char>(a));
This way, even if you clear the 'main' list, in your class you'll have 1 as items count.
Hope this helps.
List and other classes are reference types. In few words, it means you have an object somewhere in memory and a reference(s) on it.
this.l = l; means you copied the reference to the first list to the class field. So you have one list and two references on it. And when you clear the list via a variable, no matter how you address it after clearing - via a or cl.l. Your single list is cleared already.
If you want to avoid this, you need to create a copy of list in your constructor:
public cl(List<char> l)
{
this.l = new List<char>();
this.l.AddRange(l);
}
}
I recommend you to read more information about reference types. They are used widely and knowledge about them will give you a good base for programming skills.
if (a is System.ValueType)
{
//never
Console.WriteLine("List is value type");
}
if ('s' is System.ValueType)
{
//always
Console.WriteLine("char is value type");
}
I think you know, char is value type, but list is reference type.
Even code like this; it would be same.
List<char> a = new List<char>();
a.Add('s');
List<char> c = a;
a.Clear();
Console.WriteLine(c.Count);

Is encapsulate a private field into a variable a good practice? C# [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For example:
public class Test
{
private string _s;
public Test()
{
var s = "hello";
_s = s;
}
public void Foo()
{
var s = _s;
// Use s for some reason.
}
}
Should I use _s directly for my needs or store _s into another variable that point to it? What if there were a property instead of the private field?
First, "encapsulate" is not at all the word for what you're doing. You're talking about making a copy. In programming, to "encapsulate" means to hide the field and make everybody access it via code of some kind. In C# that almost always means a property (which is really just method calls disguised by syntactic sugar). In other languages it might be explicit get and set methods.
So. Should you make a copy?
Yes:
private int _from = 9;
public void f(int to)
{
for (int i = _from; i < to; ++i)
{
// stuff
}
}
No:
public f2()
{
Console.WriteLine("from is {0}", _from);
}
If you're going to be changing the value as you use it, but you don't want the private field to be changed, make a local copy and change that.
But beware: Value types such as int behave very, very differently than mutable reference types such as SqlConnection (see below).
If you won't be changing it, don't waste your time. In fact, if the field is a reference type and you create a local reference to it, somebody maintaining your code ages hence may mistake it for a local object and wrongly assume that changes to it won't have class-wide effects.
private SqlConnection _conn = null;
public MyClass()
{
_conn = new SqlConnection();
}
public void f3()
{
var c = _conn;
// 150 lines of stuff
// OK, I guess we're done with it now!
c.Dispose();
c = null;
// Now _conn is not null, yet the next call to f3() will find it unexpectedly
// in an invalid state. You really don't want that.
}
Where did you get this idea from?
I see no reason to proxy the private field with a local variable. Most of the time, that field will be of a reference type (i.e., more or less, a class), so using a local variable only means one more reference to that object.
It could actually be harmful (anyway, doing unintended things) if you did that with a value-type field (an int, for example). You would act on the local variable, which is fine as long as you read it; but on write the field would not be changed.

How to mimic a lambda expression returning a value [duplicate]

This question already has answers here:
Func<T> with out parameter
(4 answers)
Closed 7 years ago.
Ignoring the irrelevant parts - I have a requirement to use a delegate with no arguments and no return value, but get a value from it.
The current solution is to use a lambda expression and a variable that's declared before it.
string result;
RequiredMethod(() => { result = "the result"; });// Gets the result from a 2nd thread.
//use result
Is there a way to do this without using a lambda expression? I expect there should be, but can't come up with it.
Yes of course there is:
public class ValueHolder
{
public string Value { get; private set; }
public void AssignValue()
{
this.Value = "the result";
}
}
// usage
var vh = new ValueHolder();
RequiredMethod(vh.AssignValue);
// access value
vh.Value
The code you provided told me that you try to access values from another thread. Please keep in mind that you should not access vh.Value until AssignValue has been called. You need to add some other code to sync these operations (but your lambda has exactly the same problem).
also the question is why do you have to use a delegate. If it's about getting the value you could even implement it in a way like this
string someString;
RequiredMethod(ref someString);
Of course this would change the signature of the RequiredMethod (and the question becomes why you couldn't return a value in the first place.).
You could even write an overload of the 2nd using your lamdba expression.
void RequireMethod(string ref variable) {
RequireMethod(() => { variable = "the result";});
}

C# modifying a list in a function [duplicate]

This question already has answers here:
Directly modifying List<T> elements
(6 answers)
Closed 8 years ago.
I am writing a function which is passed in a list which is partially filled. I'd like to set some of the fields within the list inside this function. I thought that passing it as a reference would allow me to do this, however, I get the following error:
Error 1 Cannot modify the return value of 'System.Collections.Generic.List.this[int]' because it is not a variable
I am wondering what I might need to do to tell C# that I wish to have the option of modifying the contents of the list.
Here is a summarized version of my code:
public static void Determine_RTMM_Descriptor(ref List<Struct_Descriptor_Type> symbols, string Dwarf_Output_Filename)
{
...
lines = System.IO.File.ReadAllLines(Dwarf_Output_Filename);
//loop on symbol names
for (int idx = 0; idx < symbols.Count; idx++)
{
if(symbols[idx].size == 0)
symbols[idx].size = (int)new System.ComponentModel.Int32Converter().ConvertFromString(split_line[DwarfInterface.SIZE_INDEX]);
...
}
Thanks in advance for any help.
The underlying issue here is that you have a list of value types. When you use the indexer of the list to get an item from the list you are getting a copy of that type. The code symbols[idx] is the value of that item. It is not a variable representing that item, as the error message is telling you.
You're trying to mutate the size of the copy, which will have no effect on the item of the list. This is such a common mistake that the compiler even makes this an error.
If you really are sure that you want to have a mutable value type (hint: you aren't, and you shouldn't have one; you almost certainly just want to have a class here to avoid this problem entirely) then you would need to get the value of the item, mutate it, and then set the item again:
if(symbols[idx].size == 0)
{
var symbol = symbols[idx];
symbol.size = 42;
symbols[idx] = symbol;
}
Your return type on the function is "void" when you should set the return type to the list. That should allow you to change it and return it modified.

Categories