List with items returns empty - c#

I have created a simple List function but if I Loop through the List it's empty. It should not be!
// List function
public class process_hook
{
public static List<String> pro_hook = new List<String>
(new String[] { list_all_pocesses() });
protected static string list_all_pocesses()
{
StringBuilder _list = new StringBuilder();
foreach (Process i in Process.GetProcesses("."))
{
try
{
foreach (ProcessModule pm in i.Modules)
{
pro_hook.Add(pm.FileName.ToString());
}
}
catch { }
}
return _list.ToString();
}
}
// call
private void button1_Click(object sender, EventArgs e)
{
foreach (String _list in process_hook.pro_hook)
{
Console.WriteLine(_list);
}
}

Well this is a problem to start with:
catch { }
If anything goes wrong, you'll just silently abort.
Maybe that's what's happening? (EDIT: It is. See later.)
The next problem is that your "list" will only ever contain a single string... is that really what you intended? I doubt that the list you're seeing is actually empty - but it will contain a single empty string.
(As a side note, I would strongly suggest that you start following .NET naming conventions and avoid global variables like this.)
EDIT: Aargh - I've just realized what you've done. You're probably actually getting a NullReferenceException in list_all_pocesses, which you've caught and ignored.
Your call to pro_hook.Add is made before you've assigned a value to pro_hook. Basically you've got a variable initializer which uses a method which in turn uses the variable. Don't do that. If you step through your code in the debugger, you may get more of an idea of what's going on, but basically you've created a big ball of spaghetti for yourself.
Why doesn't list_all_pocesses just return a List<string>? Why are you using a StringBuilder at all?

Well... you're returning an empty string builder. That's your problem. Your code is doing what you're telling it to do. :)
return _list.ToString();

public class process_hook
{
public static List<string> pro_hook = list_all_pocesses();
protected static List<string> list_all_pocesses()
{
List<string> list = new List<string>();
foreach (Process i in Process.GetProcesses("."))
{
foreach (ProcessModule pm in i.Modules)
{
list.Add(pm.FileName.ToString());
}
}
return list;
}
}

_list.ToString() is not going to return any meaningful value. Try something like this instead:
public static List<string> pro_hook = list_all_processes();
protected static List<string> list_all_processes()
{
var list = new List<string>();
foreach (Process i in Process.GetProcesses(".")) {
try {
foreach (ProcessModule pm in i.Modules) {
list.Add(pm.FileName);
}
} catch { }
}
return list;
}

Related

States List: Foreach Loop

I have adapted some code that generates a random state value (below)
public static string GenRandomState()
{
List<string> lst = new List<string>();
randomState = string.Empty;
lst.Add("Alabama");
lst.Add("Alaska");
lst.Add("Arizona");
...
randomState = lst.OrderBy(xx => rnd.Next()).First();
return randomState;
} // End GenRandomState
I would like to remove the randomization and, instead, have the method call the states in the same order (Top to Bottom) each time the method is called.
So, what I'd like to see is this: each iteration, a state value (starting at the top) will be retrieved. The execution will continue until all the state values have been called. I think a Foreach loop would be appropriate but I am not sure how best to implement.
Because you are leaving the loop and only selecting one state each call I would not use a foreach loop and instead keep a index variable and use that to choose which index you are going to use.
First, I would move the creation of the list outside of the function so it is only done once.
public class StateInfo
{
static StateInfo()
{
lst.Add("Alabama");
lst.Add("Alaska");
lst.Add("Arizona");
...
}
static readonly List<string> _lst = new List<string>();
static readonly object _listLock = new object();
static int _nextIndex = 0;
public static string GetNextState()
{
int i = 0;
lock(_listLock)
{
i = _nextIndex;
_nextIndex = (_nextIndex + 1) % _lst.Count;
}
return _lst[i];
}
}
You can change the function to return an IEnumerable.
static void Main(string[] args)
{
foreach (var s in GetStates())
{
Console.WriteLine(s);
}
}
public static IEnumerable<string> GetStates()
{
var lst = new List<string>();
lst.Add("Alabama");
lst.Add("Alaska");
lst.Add("Arizona");
...
return lst;
}

When to use generics and type checking?

Assume A through Z to be 26 classes I defined. In the following example:
private List<A> _listA;
private List<B> _listB;
// private List<C>, and so on, through...
private List<Z> _listZ;
private void setLabelA()
{
LabelA.Text = _listA.Count;
}
// private void setLabelB() exists
// and so does setLabelC()
// and so on, all the way through to...
private void setLabelZ()
{
LabelA.Text = _listZ.Count;
}
It seems to me that there is no way to shorten this other than the following:
private void setLabel<genericType>(List<genericType> list)
{
if(list is List<A>) LabelA.Text = _listA.Count;
else if(list is List<B>) LabelB.Text = _listB.Count;
else if(list is List<C>) LabelC.Text = _listC.Count;
// and so on...
else if(list is List<Z>) LabelZ.Text = _listZ.Count;
}
Overloading the function name doesn't reduce the number of lines of code:
private void setLabel(List<A> list)
{
LabelA.Text = _listA.Count;
}
private void setLabel(List<B> list)
{
LabelB.Text = _listB.Count;
}
I prefer to use the is operator to determine which Label to set, because it preserves space (in this scenario, 50 lines of meaningless brackets and 25 lines of slightly-different function names). However, a Stack Overflow user recommended that I not use generics, and instead use separate functions, one for each Label. Although this solution will work, I prefer to not do so.
Is there any benefit towards NOT using the is operator, and towards explicitly typing my functions?
The benefit is that your type checking is static, rather than dynamic. If someone passes in a List<SomeRandomeClassYouDontSupport> to the first method, then the code will compile and just not work properly at runtime. It'll either do nothing, throw an exception, or whatever you code it to do, but the point is that the caller won't be able to see that they did something wrong until they run the code.
When you have multiple overloads then the validation is done at compile time. If an unsupported type is provided then the code won't even compile rather than compiling and not working.
It's also an important semantic difference. Generics are there to say, "This method will work regardless of what the type is". When creating a list there are no right and wrong type arguments to provide. You can create a list of any type that you want. That's an appropriate use of generics, because lists are a conceptually generic data structure. Having several overloads is a way of saying, "This finite list of types is supported." You're in the latter case, so that makes that behavior clearer to the caller, so they'll understand what the method needs to do just by looking at its signature.
Having said all of that, it looks like this isn't even a situation where you should be doing either. If you really wanted to have a method accepting one of a finite number of types known at compile time as a parameter, overloads are the right way to do it, but in your case, you shouldn't be doing any of this at all. You should be binding these UI compontents to a view as mentioned in this comment.
Why not just make your own classes which derive their own fields automatically?
private class ListWithText : List<T>
{
int Text {
get { return this.Count; }
}
}
ListWithText<A> LabelA = new ListWithText<A>();
Console.WriteLine(LabelA.Text);
I will NOT comment about whether it is a good practice or not to do what you are doing :).
If the absence of a label for a given list is NOT the end of the world for you and if you rely on some naming conventions for your label fields so that all labels are named for example "LabelX" where X is your type that will be used for generic lists, you can do that:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Labels
{
class Program
{
static void Main(string[] args)
{
Container c = new Container();
c.ApplyLabels();
}
}
public class A
{
}
public class B
{
}
public class C
{
}
public class Container
{
private Label LabelA = new Label ();
private Label LabelB = new Label ();
private Label LabelC = new Label ();
private List<A> _listA = new List<A> ();
private List<B> _listB = new List<B> ();
private List<C> _listC = new List<C> ();
public void ApplyLabels ()
{
var allFields = this.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Dictionary<Type, FieldInfo> listFields = new Dictionary<Type, FieldInfo>();
Dictionary<Type, FieldInfo> labelMappings = new Dictionary<Type, FieldInfo>();
Dictionary<string, Type> namespacesForListGenericTypes = new Dictionary<string, Type>();
List<FieldInfo> possibleLabelFields = new List<FieldInfo>();
foreach (var field in allFields)
{
if (field.FieldType.IsGenericType)
{
var genericTypeDef = field.FieldType.GetGenericTypeDefinition();
if (genericTypeDef == typeof (List<>))
{
var genericArgument = field.FieldType.GetGenericArguments()[0];
listFields.Add(genericArgument, field); // remember list fields and for each list what generic type it has!
namespacesForListGenericTypes[genericArgument.Name] = genericArgument;
}
}
else if (typeof (Label).IsAssignableFrom (field.FieldType))
{
possibleLabelFields.Add(field);
}
}
foreach (var possible in possibleLabelFields)
{
if (possible.Name.Length < 6) continue;
var typeName = possible.Name.Substring(5);
Type genericListType;
if (namespacesForListGenericTypes.TryGetValue (typeName, out genericListType))
{
labelMappings[genericListType] = possible;
}
}
foreach (var list in listFields)
{
FieldInfo destination;
if (false == labelMappings.TryGetValue (list.Key, out destination))
{
continue;
}
var destinationLabel = destination.GetValue(this) as Label;
if (destinationLabel == null) continue;
var listValue = list.Value.GetValue(this) as IList;
var cnt = listValue == null ? 0 : listValue.Count;
destinationLabel.Text = cnt.ToString();
}
}
}
public class Label
{
public string Text { get; set; }
}
}

Cannot add an item to a List in a constructor of a user control's base class

I seem to be getting a null reference error when I try to add an item to a list in the constructor of my CustomCheckoutProcess class. This class is inherited by a user control's class, so its default constructor is called when the control's constructor is called (I believe that's how it works).
Here's the relevant parts of the class definition for the checkout process (error seems to be line 12 - marked with a comment on line 11):
public class CustomShoppingCart : ShoppingCart {
private List<CheckoutProcessArgument> checkoutProcessArguments = List<CheckoutProcessArgument>();
public CustomShoppingCart()
{
GetBaseCartSteps();
CheckoutProcessArgument stepTwoArg = new CheckoutProcessArgument("Step2", new Guid("12345678-1234-1234-1234-123456789012"));
// when I comment this line out, everything works fine
checkoutProcessArguments.Add(stepTwoArg);
BuildCheckoutProcess();
}
private void GetBaseCartSteps()
{
baseCartSteps = new Dictionary<string, int>();
// iterate through base cart's steps and grab name/index pairs
foreach (CheckoutProcessStepInfo step in this.CheckoutProcessSteps)
{
baseCartSteps.Add(step.Name, step.StepIndex);
}
}
private bool CartContains(Guid productGuid)
{
for (int i = 0; i < ShoppingCartInfoObj.CartItems.Count; i++)
{
if (ShoppingCartInfoObj.CartItems[i].SKU.SKUGUID == productGuid)
{
return true;
}
}
return false;
}
private void BuildCheckoutProcess()
{
// create a list of ints to dynamically add or remove the indexes of the base cart's steps
List<int> steps = new List<int>();
if (checkoutProcessArguments != null)
{
// add steps if they are specified in the arguments list
foreach (CheckoutProcessArgument argument in checkoutProcessArguments)
{
if (CartContains(argument.ProductGUID))
{
int stepIndexToAdd;
baseCartSteps.TryGetValue(argument.StepName, out stepIndexToAdd);
steps.Add(stepIndexToAdd);
}
}
}
// sort the steps so that they'll be in the correct order
steps.Sort();
customSteps = new int[steps.Count];
customSteps = steps.ToArray();
}
}
And here's the struct that I'm using to create arguments for a custom checkout process:
public struct CheckoutProcessArgument
{
private string stepName;
private Guid productGUID;
public string StepName { get { return stepName; } }
public Guid ProductGUID { get { return productGUID; } }
public CheckoutProcessArgument(string stepName, Guid productGuid)
{
this.stepName = stepName;
this.productGUID = productGuid;
}
}
Here's the stack trace for the error I recieve:
Message: Object reference not set to an instance of an object.
Stack Trace:
at CustomShoppingCart..ctor()
...
Problem is, I can't seem to see what could possibly be null. Any ideas? I'm guessing the problem isn't that I'm adding something to a List in a constructor, but that I've bungled something else somewhere, but for the life of me I can't figure out what.
Try instantianting the list in the constructor immediately before you attempt to access it. Also, if the list is to not be assigned to again you can use the readonly keyword. Further note that we can instantiate the list and add stepTwoArg to it in a single line of code.
private readonly List<CheckoutProcessArgument> checkoutProcessArguments;
public CustomShoppingCart()
{
GetBaseCartSteps();
CheckoutProcessArgument stepTwoArg = new CheckoutProcessArgument("Step2", new Guid("12345678-1234-1234-1234-123456789012"));
checkoutProcessArguments = new List<CheckoutProcessArgument> { stepTwoArg };
BuildCheckoutProcess();
}

How to set one ObservableCollection to another ObservableCollection?

Basically, I want to know if I can do this with two ObservableCollections:
oldList = newList;
I have two lists that get populated throughtout my app, and each time they get populated, I want the 'new' values to become the 'old' values, and then get a new set of values to put in the 'new' list.
is it that easy? Any other way to do this without iterating over the whole newList every time?
EDIT: This is how the new list is being populated. Basically, I just want the contents of the newList to be put into the oldList.
foreach (object obj in ts.GetVariables())
{
if ((obj.ToString() != "_SMSTSReserved2") || (obj.ToString() != "OSDJoinPassword") || (obj.ToString() != "OSDLocalAdminPassword"))
{
TSVar var = new TSVar();
var.TSVarName = obj.ToString();
var.TSVarValue = ts[obj.ToString()];
newList.Add(var);
}
}
oldList.Clear();
foreach (TSVar var in newList)
{
oldList.Add(var);
}
If you use the extension method listed below, what you are trying to do becomes a one liner:
oldList.Replace(newList);
I would create an Extension Method for ObservableCollection like this:
public static class ObservableCollectionExtensionMethods
{
public static void Replace<T>(this ObservableCollection<T> old, ObservableCollection<T> #new)
{
old.Clear();
foreach (var item in #new)
{
old.Add(item);
}
}
}
And this is how you would use it:
using System.Collections.ObjectModel;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace ExtensionMethods
{
[TestClass]
public class ObservableCollectionExtensionMethodsTest
{
[TestMethod]
public void ReplaceTest()
{
// Arrange
var old = new ObservableCollection<string> { "1"};
var #new = new ObservableCollection<string> {"2"};
// Act
old.Replace(#new);
// Assert
Assert.AreEqual("2", old.First());
}
}
}
I think this is what you may be looking for? This will add everything that was in newList to your oldList.
ObservableCollection<YourType> oldList = new ObservableCollection<YourType>(newList);
newList.clear();
//put new stuff in your list here.

C# Reading each value of a returned array

I have an array being returned but as I'm new to programming I can't work out how to read each value. Can someone please point me in the right direction?
My code is below.
private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (int name in getNames()) //<----I'm wrong here I guess
{
MessageBox.Show(name.ToString());
}
}
private ArrayList getNames()
{
//some code...
..
...
return names;
}
Thanks all
Firstly, you're not returning an array, but rather an ArrayList instance. Secondly, why would a name be an int? Surely you mean string? Finally, if you're on .NET 2.0 or later, you can use generics to improve your code. So, use List<string> rather than ArrayList.
private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (string name in getNames())
{
MessageBox.Show(name);
}
}
private List<string> GetNames()
{
var names = new List<string>();
names.Add("Kent");
return names;
}
The issue here is that getNames returns an arraylist of objects--not ints.
You could rewrite your code with this change:
foreach (object nameobj in getNames())
{
string name = (string)nameobj;
MessageBox.Show(name);
}
Alternatively, you could (and should) use generics to keep everything nice and tidy. That might look like this (untested) code:
private void testToolStripMenuItem_Click(object sender, EventArgs e)
{
foreach (string name in getNames())
{
MessageBox.Show(name);
}
}
private IList<string> getNames()
{
//some code...
List<string> names = new List<string>();
names.Add("Scott");
..
...
return names;
}
Add a using for System.Collections.Generic. Also, as others noticed, I changed it to string from int.
Rather than using ArrayList, try using List<int>.
I'm guessing that in the foreach statement, you're hitting a cast exception. It's hard to tell this because you've left out the body of getNames().
Try return a list of int instead. Like this:
private List<int> getNames()
{
//some code...
..
...
return names;
}
Either that, or check that it's really int's in your list, so you've not done anything like list.add("5"). Then the 5 would be a string, not an int.
ArrayList stores items as objects. So you need to unbox it to the required type (int in your case). But why int and not string for name?
This may get you started:
String key, val;
foreach (DictionaryEntry de in myArrayList)
{
key = (String)de.Key;
val = (MyObjectType)de.Value;
}
EDIT: Updated to remove the IEnumerator version to a foreach version.

Categories

Resources