I'm trying to add one list to another . So I have this main list that I'm going to build. I loop through records and built a list and want this list to main list every time I loop. I'm trying to do this in C#.
I'm using following code. Add() function is not working.I'm getting syntax error.
IList<CgValDetail> cgValDetail = null;
//Get cgValDetails for each control
foreach (UiControlScreenMetaData tempUiControls in uiControls)
{
if (tempUiControls.CgValId == null)
{
continue;
}
IList<CgValDetail> tempCgValDetail = Retrieval<CgValDetail>.Search(new { CgValId = tempUiControls.CgValId }).ToList();
if (!tempCgValDetail.Any())
{
_foundationService.LogBusinessError(null, new ParameterBuilder("CgValId", tempUiControls.CgValId), "Invalid_CgValId_found");
return false;
}
//Add tempCgValDetail List to main list which is cgValDetail
cgValDetail.Add(tempCgValDetail);
}
Take a look at AddRange.
var firstList = new List<string>();
var secondList = new List<string>() { "a", "b" };
firstList.AddRange(secondList);
You mentioned that you don't have access to AddRange... The problem is that you're using an IList, which doesn't implement AddRange. Check this out for more on why: Why doesn't IList support AddRange
I would advise you to switch to List.
First, you need to instantiate cgValDetail as a new list, not a null.
Then you should decide if you want to declare cgValDetail as IList instead of a List. If yes, try this:
IList<CgValDetail> cgValDetail = new List<CgValDetail>();
//Get cgValDetails for each control
foreach (UiControlScreenMetaData tempUiControls in uiControls)
{
if (tempUiControls.CgValId == null)
{
continue;
}
IList<CgValDetail> tempCgValDetail = Retrieval<CgValDetail>.Search(new { CgValId = tempUiControls.CgValId }).ToList();
if (!tempCgValDetail.Any())
{
_foundationService.LogBusinessError(null, new ParameterBuilder("CgValId", tempUiControls.CgValId), "Invalid_CgValId_found");
return false;
}
//Add tempCgValDetail List to main list which is cgValDetail
((List<CgValDetail>)cgValDetail).AddRange(tempCgValDetail);
}
But I wonder why just not using a List instead of IList.
List<CgValDetail> cgValDetail = new List<CgValDetail>();
//Get cgValDetails for each control
foreach (UiControlScreenMetaData tempUiControls in uiControls)
{
if (tempUiControls.CgValId == null)
{
continue;
}
List<CgValDetail> tempCgValDetail = Retrieval<CgValDetail>.Search(new { CgValId = tempUiControls.CgValId }).ToList();
if (!tempCgValDetail.Any())
{
_foundationService.LogBusinessError(null, new ParameterBuilder("CgValId", tempUiControls.CgValId), "Invalid_CgValId_found");
return false;
}
//Add tempCgValDetail List to main list which is cgValDetail
cgValDetail.AddRange(tempCgValDetail);
}
Your cgValDetail is null. That's why when you add(...), you get syntax error.
Create a new IList<CgValDetail>
IList<CgValDetail> cgValDetail = new List<CgValDetail>();
Why didn't you use List<T> in stead of IList<T>?
You forgot to new it.
Just a simple example:
List<a> aList= new List<a>();
List<aList> List_aList = new List<aList>();
List_aList.add(new aList());
Here the link to same question.
Maybe, you can use "UNION" in Linq (if you don't really care about performance or result set is not big enough).
cgValDetail.Add(tempCgValDetail);
change to
cgValDetail = cgValDetail.Union(tempCgValDetail.Select(a => a)).ToList();
Related
I noticed interesting action, when I change list inside some method, and throw exception inside this method, then out of scope of the method list is not changed.
How to change force this list to be changed in catch block? using out ?
List<string> list = null;
try
{
list = new List<string>{"1", "2", "3"};
ChangeMyList(list);
}
catch
{
//here list has 3 elements , why ?
}
void ChangeMyList(List<string> list)
{
list = list.Except(new List<string>{"1", "2"}).ToList();
//here this list has only one element
throw new Exception();
}
Inside ChangeMyList, list is a copy of the reference to the source list pointed to by list in the outer scope. Assigning to this local reference does not affect the reference in the caller. You can use ref to pass list by reference:
void ChangeMyList(ref List<string> list)
{
list = list.Except(new List<string>("1", "2")).ToList();
//here this list has only one element
throw new Exception();
}
then
List<string> list = new List<string>{"1", "2", "3"};
ChangeMyList(ref list);
This is not because of the exception; your list is not being changed because the reference to it is copied when you call the function, as in, list in your function is a copy of list in the parent scope, and any changes to it won't be made to the original one.
You have two solutions:
Either make your function return list, and store it back into the original variable:
try {
having List<string> list = new List<string>{"1", "2", "3"};
list = ChangeMyList(list);
} catch() {
}
List<string> ChangeMyList(List<string> list)
{
list = list.Except(new List<string>("1", "2"));
return list;
}
Or you can simply pass your list with the ref keyword to indicate that the function will modify it:
try {
having List<string> list = new List<string>{"1", "2", "3"};
ChangeMyList(ref list);
} catch() {
}
void ChangeMyList(ref List<string> list)
{
list = list.Except(new List<string>("1", "2"));
}
The answer was already given but just for those who, like me, understand it better in a graphical way:
Consider the the piece of code below. I need to call the method CreateOrAddToLists() in a loop. First time the method is called the two lists casedata.Cases and casedata.Documents will be null, hence I can populate by assigning cases to casedata.Cases like this:
casedata.Cases = cases;
At any subsequent call to CreateOrAddToLists() lists casedata.Cases and casedata.Documents will not be null and I can add new data to the lists using AddRange():
casedata.Cases.AddRange(cases);
var casedata = new CaseData(); //contains lists to get populated
private void CreateOrAddToLists()
{
var cases = new List<Case>(); //gets data with from database
var documents = new List<Document>(); //gets data with from database
if (casedata.Cases == null)
{
casedata.Cases = cases;
}
else
{
casedata.Cases.AddRange(cases);
}
if (casedata.Documents == null)
{
casedata.Documents = documents;
}
else
{
casedata.Documents.AddRange(documents);
}
}
Is there a better or neater way to do a null-check before AddRange? Can I do it in on line of code?
In the constructor for CaseData instantiate the two list objects, then you'll be assured they won't be null and you can just use AddRange.
public CaseData()
{
Cases = new List<Case>();
Documents = new List<Document>();
}
It's more clear:
casedata.Cases = casedata.Cases ?? new List<Case>();
casedata.Cases.AddRange(cases);
casedata.Documents = casedata.Documents ?? new List<Document>();
casedata.Documents.AddRange(documents);
I have a class named DataAPIKey. I have a second class which inherits from that one.
In my code I have a List, and I would like to use that to make a list of the new class. Is there any way to do this without using a for each loop?
Using the example below I made the following code which seems to be doing what I want.
List<DataAPIKey> apiList = db.GetPendingAction("Character");
List<DataCharacter> charList = apiList.Select(k => {
DataCharacter dc = new DataCharacter(k.apiKeyId, k.keyId, k.verificationCode);
return dc;
}).ToList()
Use the LINQ Select method.
var newList = oldList.Select(oldItem => new InheritedItem(oldItem)).ToList();
In plain English this translates to "Take each item from oldList, feed each as a function parameter to a function which will take that item and perform some logic to return a different type of item, then take all the returned items and populate them into a new List."
Or if you don't have a constructor to initialize the inherited class then you can provide any code block:
var newList = oldList.Select(oldItem =>
{
var newItem = new InheritedItem();
newItem.Property = oldItem.Property;
return newItem;
}).ToList();
Or an initializer:
var newList = oldList.Select(oldItem => new InheritedItem()
{
Property = oldItem.Property,
Property2 = oldItem.Property2
}).ToList();
I have got a complete list of my brands to appear in my DropDownBox, however there appears to be no order (simply how they are input into the database) and I need to sort them into alphabetical order.
But it doesn't look like I can use the .Sort(); on an IList and there doesn't seem to be anything similar on ILists so I am at a bit of a loss, I have tried to convert the IList into a List and then using the List.Sort() method but I have had no luck with this as it just comes back unsorted again:
public void BrandListRetrieve()
{
var factory = new BrandFactory();
var customBool1State =
factory.ByCustomBoolean1(false, CoreHttpModule.Session);
if (customBool1State != null)
{
var brandDropDown = CoreHttpModule
.Session
.CreateCriteria(typeof(Brand)).List<Brand>();
foreach (Brand brand in brandDropDown)
{
this.Items.Add(brand.Name);
}
if (this.Items.Count < 0)
{
this.Items.Insert(0, new ListItem("Hello World", "Hello World"));
}
var brandList = brandDropDown as List<string>;
if (brandList != null)
brandList.Sort();
}
}
you should try this;
foreach (Brand brand in brandDropDown.OrderBy(b => b.Name))
You can certainly REMOVE the following lines from your code;
var brandList = brandDropDown as List<string>;
if (brandList != null)
brandList.Sort();
it seems that you need to use brand.Sort() with Compare method. Try to read this manual http://msdn.microsoft.com/en-us/library/w56d4y5z.aspx
How do I transfer the items contained in one List to another in C# without using foreach?
You could try this:
List<Int32> copy = new List<Int32>(original);
or if you're using C# 3 and .NET 3.5, with Linq, you can do this:
List<Int32> copy = original.ToList();
I see that this answer is still getting upvotes. Well, here's a secret for ya: the above answer is still using a foreach. Please don't upvote this any further.
To add the contents of one list to another list which already exists, you can use:
targetList.AddRange(sourceList);
If you're just wanting to create a new copy of the list, see the top answer.
For a list of elements
List<string> lstTest = new List<string>();
lstTest.Add("test1");
lstTest.Add("test2");
lstTest.Add("test3");
lstTest.Add("test4");
lstTest.Add("test5");
lstTest.Add("test6");
If you want to copy all the elements
List<string> lstNew = new List<string>();
lstNew.AddRange(lstTest);
If you want to copy the first 3 elements
List<string> lstNew = lstTest.GetRange(0, 3);
And this is if copying a single property to another list is needed:
targetList.AddRange(sourceList.Select(i => i.NeededProperty));
This method will create a copy of your list but your type should be serializable.
Use:
List<Student> lstStudent = db.Students.Where(s => s.DOB < DateTime.Now).ToList().CopyList();
Method:
public static List<T> CopyList<T>(this List<T> lst)
{
List<T> lstCopy = new List<T>();
foreach (var item in lst)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, item);
stream.Position = 0;
lstCopy.Add((T)formatter.Deserialize(stream));
}
}
return lstCopy;
}
Easy to map different set of list by linq without for loop
var List1= new List<Entities1>();
var List2= new List<Entities2>();
var List2 = List1.Select(p => new Entities2
{
EntityCode = p.EntityCode,
EntityId = p.EntityId,
EntityName = p.EntityName
}).ToList();
Adding to the top answers, if you want copies of "the objects in the list", then you can use Select and make the copies. (While the other answers make "a copy of a list", this answer makes "a list of copies").
Suppose your item has a Copy method:
List<MyObject> newList = oldList.Select(item => item.Copy()).ToList();
Or that you can create a new object from the previous one with a constructor:
List<MyObject> newList = oldList.Select(item => new MyObject(item)).ToList();
The result of Select is an IEnumerable<MyObject> that you can also pass to AddRange for instance, if your goal is to add to an existing list.
OK this is working well
From the suggestions above GetRange( ) does not work for me with a list as an argument...so sweetening things up a bit from posts above: ( thanks everyone :)
/* Where __strBuf is a string list used as a dumping ground for data */
public List < string > pullStrLst( )
{
List < string > lst;
lst = __strBuf.GetRange( 0, __strBuf.Count );
__strBuf.Clear( );
return( lst );
}
public static List<string> GetClone(this List<string> source)
{
return source.Select(item => (string)item.Clone()).ToList();
}
Here another method but it is little worse compare to other.
List<int> i=original.Take(original.count).ToList();