Issues trying to get Index Location in IList - c#

class IList2
{
static void Main(string[] args)
{
Locations test = new Locations();
Location loc = new Location();
string sSite = "test";
test.Add(sSite);
string site = loc.Site;
Location finding = test.Where(i => i.Site == site).FirstOrDefault();
int index = finding == null ? -1 : test.IndexOf(finding);
}
}
public class Location
{
public Location()
{
}
private string _site = string.Empty;
public string Site
{
get { return _site; }
set { _site = value; }
}
}
public class Locations : IList<Location>
{
List<Location> _locs = new List<Location>();
public Locations() { }
public int IndexOf(Location item)
{
return _locs.IndexOf(item);
}
//then the rest of the interface members implemented here in IList
public void Add(string sSite)
{
Location loc = new Location();
loc.Site = sSite;
_locs.Add(loc);
}
}
IEnumerator<Location> IEnumerable<Location>.GetEnumerator()
{
return _locs.GetEnumerator();
}
I got helped a bit in this post: Trying to call int IList<Location>.IndexOf(Location item) method
I tried to get this working but I always seem to get -1 as the index number. I know string site = loc.Site; is empty after realizing that so I don't know exactly how to get the index from the IList at this point.
To clear up what I'm trying to accomplish, I want to learn how to use the IList interface members and I started out with the IndexOf interface.
The IList is populated with more than just "sSite" but I just reduce the list to just "sSite" for an example purpose.
So in the middle of learning, I hit this bump in the road and been staring at the code for a few days (yes I take breaks and look at other stuff as not to tire myself out).
So the main issue is that I keep getting index = -1.

I'm not clear on what your intention is here but in the code snippet "loc" is never used because you create a new Location in the "Add" method and "site" is (as you've noted) always empty but in the "Add" method you pass in a value and set it on the newly created instance so unless you passed string.Empty as a value the comparison i.Site == site will always be false. If you remove those and rewrite as:
Locations test = new Locations();
string sSite = "test";
test.Add(sSite);
Location finding = test.Where(i => i.Site == sSite).FirstOrDefault();
int index = test.IndexOf(finding);
Then this returns 0 as the index.

Assuming that you have this in the beginning:
Location loc = new Location();
loc.Site = "test";
You will get your index.
Also it is bit confusing, because very unclear what you want to accomplish here.
Note that this line of code:
test.Where(i => i.Site == site).FirstOrDefault();
will return you value only if following is true: "i.Site == site", of course which cannot happen if you provide something not existing in list.

Related

How do we assign a current property to be equal to new parameter and then remove it when a new value is assined?

The test should check when a train is assigned to a line he losts its previous line. The class Train should implement this test in the function public void AssignTo(ILine l) by following those steps (they need to be respected):
Current assignment = l1
l1.Trains contains THIS
need to remove THIS from l1.trains
need to change current line and add train to new line
internal class Train : ITrain
{
internal Train(string name, Company company)
{
this.Name = name;
this.Company = company;
}
public string Name
{
get;
}
public ICompany Company
{
get;
}
public ILine Assignment
{
get;
private set;
}
public void AssignTo(ILine l)
{
//Current assignment = l1
var l1 = Assignment;
//l1,Trains contains THIS
this.AssignTo(l1.train)
//need to remove THIS from l1.trains
((List<Train>)l1.Trains).Remove(this);
//need to change current line and add train to new line
((List<Train>)l.Trains).Add(this);
Assignment = l;
}
}
}
[Test]
public void T2_when_a_train_is_assigned_to_a_line_he_losts_its_previous_line()
{
ICity s = CityFactory.CreateCity("Paris");
ICompany c = s.AddCompany("SNCF");
ILine l1 = s.AddLine("RER A");
ILine l2 = s.AddLine("RER B");
ITrain t1 = c.AddTrain("RER1");
t1.AssignTo(l1);
t1.Assignment.Should().BeSameAs(l1);
t1.AssignTo(l2);
t1.Assignment.Should().BeSameAs(l2);
l1.Trains.Count().Should().Be(0);
l2.Trains.Single().Should().BeSameAs(t1);
}
The problem with your current interfaces are that ILine.Trains is an IEnumerable, and you can't really remove something from an IEnumerable. In your code, you have assumed that it will always be a List, which you shouldn't really do, but if you can't change the type of ILine.Trains then I guess that's the only way.
Anyway, the reason why your code doesn't work is that you are recursively calling AssignTo for some reason. You should remove this call:
public void AssignTo(ILine l)
{
var l1 = Assignment;
// remove this line
// this.AssignTo(l1.train)
((List<Train>)l1.Trains).Remove(this);
((List<Train>)l.Trains).Add(this);
Assignment = l;
}
Although this isn't required, (it seems to be one of your requirements), you need to check whether l1.Trains contains this first:
var l1 = Assignment;
if (l1.Trains.Contains(this)) {
((List<Train>)l1.Trains).Remove(this);
}
((List<Train>)l.Trains).Add(this);
Assignment = l;

How do I access List<int> value during reflection of a class?

I am fairly new to Reflection, but have been able to retrieve all fields of my passed class. Now I am trying to retrieve the values of each field, but I'm having an issue with List<T>.
I have a simple class for testing:
public class MyTestClass
{
public string Name;
public int Age;
public bool Alive;
public List<int> Counters;
public List<string> People;
public List<Tool> Tools;
public string[] Stuff;
public Tool[] NeededTools;
public MyTestClass(string name, int age, bool alive = true)
{
Name = name;
Age = age;
Alive = alive;
Counters = new List<int>();
Counters.Add(7);
People = new List<string>();
People.Add("Seven");
Tools = new List<Tool>();
Stuff = new string[2];
NeededTools = new Tool[3];
}
}
Here is the code I am using:
private void AttachControl(object source, FieldInfo fi, Control control)
{
switch (fi.FieldType.Name)
{
case "Boolean":
(control.Controls[fi.Name] as ComboBox).SelectedIndex = (fi.GetValue(source).ToString().ToUpper() == "TRUE") ? 1 : 0;
break;
case "List`1":
Control listControl = control.Controls[fi.Name];
var listType = fi.FieldType.GetGenericArguments();
var listFields = listType[0].GetFields(
BindingFlags.Public |
BindingFlags.Instance
);
if (listFields.Length > 0)
{
AttachToControls(listFields, listControl.Controls.Cast<Control>().ToArray());
}
else
{
// *** Here is the issue ***
var values = fi.GetValue(source);
listControl.Controls[fi.Name].Text = values[0].ToString();
}
break;
default:
control.Controls[fi.Name].Text = fi.GetValue(source).ToString();
break;
}
}
When I get to Counters I can retrieve the value var values = fi.GetValue(source); and during debug I can see the List with the value 7 in it, but it states
cannot apply indexing with [] to an expression of type object on the line:
listControl.Controls[fi.Name].Text = values[0].ToString();
I assume I need to cast it, but it will not always be an int type. Do I need to write a section for every type or is there an easier way to accomplish what I need?
FYI - I am writing a Class Library that will allow me to pass any class in and auto create a form to edit all fields.
I'd suggest something along the lines of:
var bob = values as IEnumerable;
listControl.Controls[fi.Name].Text = bob?.Cast<object>()?.FirstOrDefault()?.ToString();
Since the thing you want is a string (not a specific type) then the above code will work fine (assuming values is some form of an enumerable, like a list or an array).
Note, in particular, that IEnumerable interface is this one, not the more commonly used IEnumerable<T>. This allows you to use it without a specific type.

C# - How to return an Array to set a Class property

I am trying to create a Class Method which can be called to Query the Database. The function itself works but for some reason, when the Array is returned, they're not set.
My function code is:
public Configuration[] tbl_bus(string type, string match)
{
// Create Obejct Instance
var db = new rkdb_07022016Entities2();
// Create List
List<Configuration> ConfigurationList = new List<Configuration>();
// Allow Query
if (type.ToLower() == "bustype")
{
foreach (var toCheck in db.tblbus_business.Where(b => b.BusType == match))
{
// Create Class Instance
var model = new Configuration { Name = toCheck.Name, BusinessID = toCheck.BusinessID };
// Append to the property
ConfigurationList.Add(model);
}
}
else if (type.ToLower() == "businessid")
{
foreach (var toCheck in db.tblbus_business.Where(b => b.BusinessID == match))
{
// Create Class Instance
var model = new Configuration { Name = toCheck.Name, BusinessID = toCheck.BusinessID };
// Append to the property
ConfigurationList.Add(model);
}
}
return ConfigurationList.ToArray();
}
And my Configuration code is:
public class Configuration
{
// Properties of the Database
public string Name { get; set; }
public string BusinessID { get; set; }
public string Address { get; set; }
}
public Configuration Config { get; set; }
public Controller()
{
this.Config = new Configuration();
}
On my Handler I am doing:
// Inside the NameSpace area
Controller ctrl;
// Inside the Main Void
ctrl = new Controller();
ctrl.tbl_bus("bustype", "CUS");
context.Response.Write(ctrl.Config.Name);
I tried watching the Class function and it does create the Array, only, when I watch the ctrl.Config.Name it is always set to NULL. Could anyone possibly help me in understanding why the return isn't actually setting the properties inside the Configuration class?
Edit: The function does run and it fetches 3006 rows of Data when matching the bus_type to customer. (Its a large Database) - Only, the properties are never set on return.
Edit: Is there a specific way to return an Array to a Class to set the Properties?
Thanks in advance!
Change your Configs in Controller to array
public Configuration[] Configs { get; set; }
Change your tbl_bus function to void, and set the Configs inside the function.
public void tbl_bus(string type, string match)
{
// do your code
// set the configs here
Configs = ConfigurationList.ToArray();
}
Hope it helps.
Although this is not a complete answer to your question, the problem probably lies in the fact that you're not doing anything with the array returned by the method. You're simply discarding it right away. If you change your code to
ctrl = new Controller();
Configuration[] config = ctrl.tbl_bus("bustype", "CUS");
you will be able to reference the array later on.
Console.WriteLine(config.Length);
Now you can use it to set any properties you like.

Accessing Property of Class in List<Class>

I see a lot of similar questions but none with a direct answer. I have a List<ClientEntry>. I want to access properties in ClientEntry. My code looks like this:
class ClientEntry
{
private string _clientName;
private string _clientEmail;
public void ClientEntry(string name, string email)
{
this._clientName = name;
this._clientEmail = email;
}
public string ClientName
{
get
{
return _clientName;
}
set
{
_clientName = value;
}
}
public string ClientEmail
{
get
{
return _clientEmail;
}
set
{
RegexUtilities Validator = new RegexUtilities();
if (Validator.IsValidEmail(value))
{
_clientEmail = value;
}
}
}
}
Later:
private List<ClientEntry> clientList;
I then add a bunch of ClientEntry's to the List.
How can I access the ClientName and ClientEmail properties for items in clientList? Also, how can I check for the existance of a certain ClientName or ClientEmail property within the List? Is this even possible with a list of objects? I know a dict would probably serve better, but I wanted to see if this could be done with a List and a class with properties.
You can use Linq to look for values inside of a list using Any()
Eg.
bool emailExists = clientList.Any(x=>x.ClientEmail == <email>);
To access values, you can use a index accessor if you know it, loop the collection, or use Where() to search it:
var email = clientList[index].ClientEmail
or
foreach (var client in clientList)
{
var email = client.ClientEmail
}
or
var email = clientList.Where(x=>x.ClientName == <clientName>).FirstOrDefault();
you can explore your list as below
foreach (ClientEntry client in clientList)
{
//client.ClientName
//client.ClientEmail
}
to find a particular record you can search it as
clientList.Where(p=> p.ClientEmail == "email#domain.com").FirstOrDefault();
To access a specific of item in the list, you input the index / using foreach
string name = clientList[index].ClientName;
foreach(var client in clientList)
{
name = client.ClientName; // access the item one by one
}
To check the existence of certain value of a property, use linq
bool isExist = clientList.Any(i => i.ClientName == "John");
Use Extension Methods !
Something like this, you can write unit test against the extension class easily and also it's straightforward to read.
public static class ClientEntriesExtension
{
public static bool ExistEmail(this IEnumerable<ClientEntry> entries, string targetEmail)
{
return entries.Any(x=>x.ClientEmail == targetEmail);
}
}
bool exist = clientList.ExistEmail(targetEmail)

How to add a string to a ICollection<string>?

EDIT 2
I have got some help over the past few days on a problem that I am trying to work through. After receiving helpful support from several users, I have come across an error that I have been trying to fix over the weekend and still not succeeded.
I created a Dictionary, where I pass a string Country and also a ICollection of Places for that Country.
Dictionary<string, NewCountryClass> NTCD = new Dictionary<string, NewCountryClass>();
public void AddCountryCollection()
{
newCountryClass = new NewCountryClass(newCountry);
Collections.Add(newCountryClass);
NTCD.Add(newCountryClass.Country, newCountryClass);
}
public void AddPlace()
{
string Country = selectedItem.Country;
RenameQuestion(placeName);
NTCD[Country].Place.Add(placeName);
}
Here is my newCountryClass where I stored the Country and Places in that Country.
private ICollection<string> _places;
public ICollection<string> Places
{
get
{
return _places;
}
set
{
if (value == _places)
return;
_places = value;
RaisePropertyChanged(() => Places);
}
}
This is where the places could be added, but I create an instance of my class at the adding Country stage, and therefore can't pass a place at that time. (EDIT - I have moved the initialising of the collection into the constructor instead of in the Places property, as advised).
public NewCountryClass(string country)
{
_places = new ObservableCollection<string>();
if (country != null)
{
_country = country;
}
}
Therefore, I attempted to create a renamePlace() method:
public void RenamePlace(string place)
{
_places.Add(place);
}
However, _places still seems to be null even with this attempt. Any further ideas or anything I am doing wrong?
You need to learn how to debug a program. Basically, you try to instantiate your NewCountryClass here:
public void AddCountryCollection()
{ // <<< Put breakpoint here <<<
newCountryClass = new NewCountryClass(newCountry, placeName);
Collections.Add(newCountryClass);
NTCD.Add(newCountryClass.Country, newCountryClass);
}
If the placeName input parameter is null in the constructor, then it is also null here... you need to add a breakpoint here and find out why the value is null and ensure that it has a value by this stage in your program.
Would you not be better off initialising the _places collection in the constructor instead of the property get accessor?
public NewCountryClass(string country)
{
_places = new ObservableCollection<string>();
if (country != null)
{
_country = country;
}
}

Categories