Why every list is modificated in this sample? [duplicate] - c#

This question already has answers here:
Both c# lists being modified
(6 answers)
Closed 1 year ago.
I wanted to initialize my class with the list of ints for example:
{1,5,6,7,1,0} and then modify them and get two fields, one with the same list of ints and the second with a modified list of ints. But as a result, I get two modified lists with values: {0,4,5,6,0,0}. Can someone explain to me why this code acts like this?
MyClass
public class MyClass
{
public List<int> numbers { get; }
public List<int> diffrentNum { get; set; }
public MyClass(List<int> _numbers)
{
numbers = _numbers;
diffrentNum = GetNumbers();
}
private List<int> GetNumbers()
{
List<int> localNumbers = numbers;
for (int i=0;i<localNumbers.Count-1;i++)
{
if (localNumbers[i] > 0)
{
localNumbers[i]--;
}
}
return localNumbers;
}
}
Main
static void Main(string[] args)
{
List<int> someDate = new List<int>();
someDate.Add(1);
someDate.Add(5);
someDate.Add(6);
someDate.Add(7);
someDate.Add(1);
someDate.Add(0);
MyClass myclass= new MyClass(someDate);
Console.WriteLine(String.Join("", new List<int>(someDate).ConvertAll(i => i.ToString()).ToArray()));
Console.WriteLine(String.Join("", new List<int>(myclass.numbers).ConvertAll(i => i.ToString()).ToArray()));
Console.WriteLine(String.Join("", new List<int>(myclass.diffrentNum).ConvertAll(i => i.ToString()).ToArray()));
Console.ReadKey();
}

By calling List<int> localNumbers = numbers; you're assigning both variables to point to the same object, so any changes made through one of them are visible through the other.
One way to create a copy of a list is by using Linq's ToList:
List<int> localNumbers = numbers.ToList();

Related

how to query a list of objects containing multiple lists in them?

I have a list of patients.
each patient has several lists:
public class Patient
{
private List<DateTime> serverTimeStamps;
protected List<int> sessionStages;
protected List<string> revIPage;
protected List<double> current;
protected List<int> n_ok;
protected List<int> n_LE;
}
The list of patients is called ptLsit and I'm trying to get the lists items where the serverTimeStamp is bigger than _initTimeToAskData (from all the lists, not just serverTimeStamps).
The best example I can give is
ptLsit.Where(x=> x.ServerTimeStamps.Select(ts => ts >= _initTimeToAskData))
Based on this class:
public class Patient
{
public List<DateTime> serverTimeStamps;
public List<int> sessionStages;
public List<string> revIPage;
public List<double> current;
public List<int> n_ok;
public List<int> n_LE;
}
Try this:
var result = ptLsit.Where(p => p.serverTimeStamps.Any(d => d > _initTimeToAskData))
.Select(p => new Patient{
serverTimeStamps = p.Where(x => x > DateTime.Now).ToList(),
// Fill the other properties...
// ...
});
You will get the list of Patient that contains at least a DateTime bigger than the parameter _initTimeToAskData and the result objects will contain the correct dates in the serverTimeStamps property

Cannot assign new value to LINQ-selected data

namespace ConsoleApplication4
{
class T1
{
public int MyProperty { get; set; }
}
class Program
{
static void Main(string[] args)
{
var tmp = (new[] { 1, 3, 4 }).Select(x =>new T1 { MyProperty=x});
foreach (var s in tmp)
{
s.MyProperty = 9;
}
foreach (var s in tmp)
{
Console.WriteLine(s.MyProperty);
}
Console.ReadLine();
}
}
}
I expect there are three 9 on screen, but the values are still same.
However, if I modify code a little bit, the values would be changed successfully i.e. :
var tmp = (new[] { 1, 3, 4 }).Select(x =>new T1 { MyProperty=x}).ToList();
I wonder why?
The reason is deferred execution.
tmp is not a list or an array. It's only a definition how to create the enumeration. Or in other words: tmp is only the question, but not the answer.
So in the second foreach, the enumerator created by the Select is executed again, creating new instances of T1.
When you use .ToList() instead, the enumeration is converted to a List (so tmp is a List<T1>). And you can iterate that List as often as you want without creating new instances.

How to return Multiple List<> values from a single function?

trying to return 2 List values from a single function
I am using this code:-
public KeyValuePair<int, int> encrypt(string password)
{
List<int> key = new List<int>();
List<int> code = new List<int>();
/*
do stuff, do some more stuff and go!
*/
return new KeyValuePair<List<int>,List<int>>(key,code);
}
here I am trying to return 2 List<int> values but error occurs. How to return 2 list values from a single function
UPDATE
the answer is found, we got 2 correct answers thats why i didn't just pick one cause both work great
answer by HadiRj
answer by Enigmativity
and if you want to use my code then, this is the correct version of it:-
public KeyValuePair<List<int>, List<int>> encrypt(string password)
{
List<int> key = new List<int>();
List<int> code = new List<int>();
/*
do stuff, do some more stuff and go!
*/
return new KeyValuePair<List<int>,List<int>>(key,code);
}
A fairly neat way to go in this case is to use out parameters.
public void encrypt(string password, out List<int> key, out List<int> code)
{
key = new List<int>();
code = new List<int>();
/*
do stuff, do some more stuff and go!
*/
}
Change your function deceleration to
public KeyValuePair<List<int>, List<int>> encrypt(string password)
P.S: I'm not recommending this! Creating new class is better idea to handle your problem
way 1: Tuple:
public Tuple<List<int>, List<int>> func()
{
List<int> key = new List<int>() { 2,34,5};
List<int> code = new List<int>() { 345,67,7};
return Tuple.Create<List<int>,List<int>>(key, code);
}
way 2:
viewmodel
public class retViewModel
{
public List<int> key { get; set; }
public List<int> code { get; set; }
}
public retViewModel func()
{
List<int> key = new List<int>() { 2,34,5};
List<int> code = new List<int>() { 345,67,7};
retViewModel obj = new retViewModel() {
code=code,
key=key
};
return obj;
}
You can always return a List<List<int>>. From what I can see from your code the only reason why you use the KVP is because you know you are going to have two lists returned. Then I would say create another object that you can have the key and the code in it:
public class EncryptionResult
{
public IList<int> Key {get; set;}
public IList<int> Code {get; set;}
}
I don't recommend you going with the out/ref solution that some other comments suggest. It is not a good practice use them to return several parameters and they should be avoided. Also if you come to extend/modify that object at any point in time because you require more different data you don't need to change the signature of your interface however you need to modify every method and the caller if you change the parameters needed (including all your tests).
Very Simple
[WebMethod]
public static List<Teacher>[] BindData()
{
List<Teacher> list1 = new List<Teacher>();
List<Teacher> list2 = new List<Teacher>();
return new List<Teacher>[] { list1, list2 };
}
Note: Both list will use same class as i used Teacher class in both list.
List<int> key;
List<int> code;
static void Main(string[] args)
{
key = new List<int>();
code = new List<int>();
encrypt("",ref key,ref code);
}
public void encrypt(string password, ref List<int> key, ref List<int> code)
{
/*
do stuff, do some more stuff and go!
*/
}

C# get list from property and get it type [duplicate]

This question already has answers here:
How to get the type of T from a member of a generic class or method
(17 answers)
Closed 9 years ago.
I need get a type of list element.
using System;
using System.Collections;
using System.Collections.Generic;
public class Test
{
public static void Main()
{
var xClass = new XClass();
xClass.Do();
}
}
public class XClass
{
public List<string> list1 = new List<string>();
public List<string> list2 { get; set; }
public void Do()
{
// first
Console.WriteLine("Type = {0}", GetListType(list1));
// second
var propertyList = this.GetType().GetProperty("list2"); // i get list from reflection
// Create instance of list2
var newList = (IList)Activator.CreateInstance((typeof(List<>).MakeGenericType(propertyList.PropertyType)));
Console.WriteLine("Type = {0}", GetListType(newList));
}
private Type GetListType(IEnumerable list)
{
return list.GetType().GetGenericArguments()[0];
}
}
Output:
Type = System.String
Type = System.Collections.Generic.List`1[System.String]
I need to get "System.String" in second case
You can test code here http://ideone.com/uLkfBx
The statement var newList = (IList)Activator.CreateInstance((typeof(List<>).MakeGenericType(propertyList.PropertyType))); creates an instance of a generic List that contains the type of list2. So newList is of type List<List<string>> hence your result is correct.

General method to convert enum to List<T> [duplicate]

This question already has answers here:
How do I convert an enum to a list in C#? [duplicate]
(14 answers)
Closed 9 years ago.
Here's a "weird" question:
Is it possible to create a method where in it will convert whatever enum to list. Here's my draft of what I'm currently thinking.
public class EnumTypes
{
public enum Enum1
{
Enum1_Choice1 = 1,
Enum1_Choice2 = 2
}
public enum Enum2
{
Enum2_Choice1 = 1,
Enum2_Choice2 = 2
}
public List<string> ExportEnumToList(<enum choice> enumName)
{
List<string> enumList = new List<string>();
//TODO: Do something here which I don't know how to do it.
return enumList;
}
}
Just curious if it's possible and how to do it.
Enum.GetNames( typeof(EnumType) ).ToList()
http://msdn.microsoft.com/en-us/library/system.enum.getnames.aspx
Or, if you want to get fancy:
public static List<string> GetEnumList<T>()
{
// validate that T is in fact an enum
if (!typeof(T).IsEnum)
{
throw new InvalidOperationException();
}
return Enum.GetNames(typeof(T)).ToList();
}
// usage:
var list = GetEnumList<EnumType>();
public List<string> ExportEnumToList(<enum choice> enumName) {
List<string> enumList = new List<string>();
//TODO: Do something here which I don't know how to do it.
foreach (YourEnum item in Enum.GetValues(typeof(YourEnum ))){
enumList.Add(item);
}
return enumList;
}

Categories