I have a collection of objects that I want to sort alphabetically by their name property.
I have tried the following:
List<Item> itemsToSort = dataProvider.Items.ToList();
List<Item> sortedItems = itemsToSort.OrderBy(x=>x.Name).ToList();
Which doesnt work. The items are still listed in the same way as before and not alphabetically.
EDIT
Here is a more complete sample:
Class:
public class MeasureStation
{
#region Properties
public int ID
{
get { return _measureStation.ID; }
set { _measureStation.ID = value; }
}
[Required(ErrorMessage = "Navn skal udfyldes")]
public String Name
{
get { return _measureStation.Name; }
set { _measureStation.Name = value; }
}
public DateTime? DateEstablished
{
get { return _measureStation.DateEstablished; }
set { _measureStation.DateEstablished = value; }
}
public DateTime? OperationPeriodStart
{
get { return _measureStation.OperationPeriodStart; }
set { _measureStation.OperationPeriodStart = value; }
}
.
.
and so on...
}
The query is:
measureStations = dataProvider.MeasureStations.ToList();
var orderedMeasureStations = measureStations.OrderBy(x => x.Name);
When taking a look at the orderedMeasureStations query result, it looks like the following:
entry starting with:
F...
S...
a...
L...
So it is obviously not sorting by name.
I do not see how your class MeasureStation will ever work
What is _measureStation, is it this?
If it is, Then it should look like, note that the property cannot have the same name as its respective private member
public class MeasureStation
{
private int id;//private is optional as it is default
public int ID
{
get { return this.id; }
set { this.id = value; }
}
private String name;//private is optional as it is default
public String Name
{
get { return this.name; }
set { this.name = value; }
}
}
Though, it is equivalent to the class with auto-properties:
public class MeasureStation
{
public int ID {get;set;}
public String Name {get;set;}
}
So, I run against both of them
private static void Main(string[] args)
{
List<MeasureStation> itemsToSort
= new List<MeasureStation>()
{
new MeasureStation() {ID = 01, Name = "Bbbb"},
new MeasureStation() {ID = 01, Name = "Aaaa"},
new MeasureStation() {ID = 01, Name = "Cccc"}
};
List<MeasureStation> sortedItems = itemsToSort.OrderBy(x => x.Name).ToList();
Console.WriteLine("******itemsToSort*****");
foreach (var item in itemsToSort)
Console.WriteLine(item.Name.ToString());
Console.WriteLine("******sortedItems*****");
foreach (var item in sortedItems)
Console.WriteLine(item.Name.ToString());
Console.ReadLine();
}
having gotten ordered output:
******itemsToSort*****
Bbbb
Aaaa
Cccc
******sortedItems*****
Aaaa
Bbbb
Cccc
Related
public class Person {
string Name
string Address
int Age
.. 100+ more columns
}
var result = new List<Person>();
foreach (var item in result )
{
//loop column and trim the values.
}
I want the simplest way to loop the columns (assuming 100+ columns) where datatype is string then trim the value.
To rephrase in more C# terms: I want to update all properties and fields of an object that are of type string with trimmed value as item.StringProp = item.StringProp.Trim(). I don't want to manually write update for each property.
You could use reflection and Linq for filtering the properties of type string. From the OP, it looks like you are using Fields instead of properties. Please note it is unclear whether the Properties/Fields are public from OP, if you need to use public fields/properties, please use BindingFlags.Public
public List<T> TrimList<T>(List<T> source)
{
foreach(var property in typeof(T).GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(x=>x.FieldType== typeof(string)))
{
foreach(var personItem in source)
property.SetValue(personItem,Convert.ToString(property.GetValue(personItem)).Trim());
}
return source;
}
If properties, you could use
public List<T> TrimList<T>(List<T> source)
{
foreach(var property in typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).Where(x=>x.PropertyType== typeof(string)))
{
foreach(var personItem in source)
property.SetValue(personItem,Convert.ToString(property.GetValue(personItem)).Trim());
}
return source;
}
Demo Code
Note: prior to .NET 4.5 you need to pass null as a second argument:
public List<T> TrimList<T>(List<T> source)
{
foreach(var property in typeof(T).GetProperties(BindingFlags.NonPublic | BindingFlags.Instance).Where(x=>x.PropertyType== typeof(string)))
{
foreach(var personItem in source)
property.SetValue(personItem,Convert.ToString(property.GetValue(personItem,null)).Trim());
}
return source;
}
As well as reflection, another way is to make it the responsibility of the Person class.
public class Person {
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
.. 100+ more columns
public void DoTrim()
{
this.Name = this.Name.Trim();
this.Address = this.Address.Trim();
... still need to code 100+ properties
}
}
The advantage is that you can call it like this
var result = new List<Person>();
...
for(int i=0; i < result.Count(); i++)
{
result[i].DoTrim();
}
Or you can control your data in the Person class when you set it and use local private variables.
public class Person {
private string name;
public string Name
{
get { return name; }
set { name = value.Trim(); }
}
private string address;
public string Address
{
get { return address; }
set { address= value.Trim(); }
}
....
This is how I would implement it:
class Program
{
static void Main(string[] args)
{
var obj = new Person
{
MyProperty = " A",
MyProperty1 = " A ",
MyProperty2 = "A ",
MyProperty3 = "A A A",
};
TrimStrings(obj);
}
public static void TrimStrings(object obj)
{
Type stringType = typeof(string);
var properties = obj.GetType().GetProperties().Where(x => x.PropertyType == stringType);
foreach(var property in properties)
{
string value = (string)property.GetValue(obj);
property.SetValue(obj, value?.Trim());
}
}
}
public class Person
{
public string MyProperty { get; set; }
public string MyProperty1 { get; set; }
public string MyProperty2 { get; set; }
public string MyProperty3 { get; set; }
}
Output:
{"MyProperty":"A","MyProperty1":"A","MyProperty2":"A","MyProperty3":"A
A A"}
You can use This Nuget Package
.After Install use it as bellow:
result.ForEach(x => x.AdjustString());
I'm using MVVM Light in Visual Studio 2015 to build an WPF app. There's a method in the code that's repeated with slight variation 4 times in the code; the only difference is the type of the ObservableCollection being modified and the method called on the data service layer.
Here's the method, which returns an ObservableCollection of StatusViewModel objects, which are used to populate a ComboBox; the StatusVm is used for binding to the SelectedItem of the ComboBox, is set as the first item in the collection and is "blank":
private async Task<ObservableCollection<StatusViewModel>> GetStatuses()
{
var result = new ObservableCollection<StatusViewModel>();
var blank = new StatusViewModel
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await dataService.GetStatuses())
result.Add(c);
StatusVm =
result.SingleOrDefault(c => c.StatusId.Equals(-1));
return result;
}
Here's the private field and public property for StatusVm:
private StatusViewModel _statusVm;
public StatusViewModel StatusVm
{
get { return _statusVm; }
set
{
if (Equals(value, _statusVm)) return;
_statusVm = value;
RaisePropertyChanged();
}
}
Now imagine the above being repeated 3 more times, with 3 more VM types! How do I make GetStatuses() into a method that can take different view model types and call the appropriate method on the data service? Thank you.
Update: Here are the property and method for another of the types:
private MroViewModel_mroVm;
public MroViewModel MroVm
{
get { return _mroVm; }
set
{
if (Equals(value, _mroVm)) return;
_mroVm = value;
RaisePropertyChanged();
}
}
private async Task<ObservableCollection<MroViewModel>> GetMro()
{
var result = new ObservableCollection<MroViewModel>();
var blank = new MroViewModel
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await dataService.GetMro())
result.Add(c);
MroVm =
result.SingleOrDefault(c => c.StatusId.Equals(-1));
return result;
}
You would create interface for common properties.
internal interface IStatusViewModel {
int StatusId { get; set; }
string Status { get; set; }
string Description { get; set; }
bool IsActive { get; set; }
DateTime CreatedDate { get; set; }
}
Implement the interface in classes that you need to retrieve status for
internal class MroViewModel : IStatusViewModel {
public int StatusId { get; set; }
public string Status { get; set; }
public string Description { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedDate { get; set; }
}
Make method static and pass the service function which will call appropriate method to retrieve old statuses.
public static async Task<ObservableCollection<T>> GetStatuses<T>(
Func<MyDataService, Task<IEnumerable<T>>> retrieveStatusesAction)
where T : IStatusViewModel, new()
{
var result = new ObservableCollection<T>();
var blank = new T
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await retrieveStatusesAction(dataService))
result.Add(c);
// TODO Implement Expression<Func<TSource, TResult>> projection for assigning to VM
StatusVm = result.SingleOrDefault(c => c.StatusId.Equals(-1));
return result;
}
You would then call this method like so:
GetStatuses((service) => service.GetMro());
I didn't test this and the StatusVm needs to be assigned using expression compilation. I will take a look at how to do that now, but the idea is there.
For the Expression and property assigning:
Property selector Expression<Func<T>>. How to get/set value to selected property
-- EDIT --
Something like this for VM assignment:
public static async Task<ObservableCollection<T>> GetStatuses<T, TContainer>(
TContainer instance,
Expression<Func<TContainer, T>> viewModelProjection,
Func<MyDataService, Task<IEnumerable<T>>> retrieveStatusesAction)
where T : IStatusViewModel, new()
{
var result = new ObservableCollection<T>();
var blank = new T
{
StatusId = -1,
Status = null,
Description = null,
IsActive = false,
CreatedDate = DateTime.Now
};
result.Add(blank);
var dataService = new MyDataService();
foreach (var c in await retrieveStatusesAction(dataService))
result.Add(c);
var vmStatus = result.SingleOrDefault(c => c.StatusId.Equals(-1));
// Warning: Check casted values, this is unsafe
var vm = (PropertyInfo)((MemberExpression)viewModelProjection.Body).Member;
vm.SetValue(instance, vmStatus, null);
return result;
}
You would then call the method like this:
await GetStatuses(this, inst => inst.MroVm, (service) => service.GetMro());
If you are not familiar with expressions, I will explain.
First argument is object in which view model instance is located. Second argument selects the property from that object that corresponds to the view model that needs to be changed. Last argument is function that takes the service and returns appropriate method that retrieves the statuses - this is like pointer to the function in C++.
This will compile, but not sure if it will behave as expected. It should. If you have any problems, please write them down in comments.
You could define interfaces and try a combo of Strategy and Factory, like the following (I skipped async/await for simplicity):
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Starting");
var mainVm = new MainViewModel();
mainVm.GetStatuses();
mainVm.GetMro();
Console.WriteLine("Status: {0} {1}", mainVm.StatusVm.Name, mainVm.StatusVm.CreateDate);
Console.WriteLine("MroVm: {0} {1}", mainVm.MroVm.Name, mainVm.MroVm.CreateDate);
}
}
public class MainViewModel
{
public StatusViewModel StatusVm { get; set; }
public MroViewModel MroVm { get; set; }
public void GetStatuses()
{
var result = Get(VmKind.Status);
StatusVm = result.SingleOrDefault(c => c.StatusId.Equals(-1)) as StatusViewModel;
}
public void GetMro()
{
var result = Get(VmKind.Mro);
MroVm = result.SingleOrDefault(c => c.StatusId.Equals(-1)) as MroViewModel;
}
public IEnumerable<IVm> Get(VmKind vmKind)
{
var dataService = new MyDataService();
return dataService.Get(vmKind);
}
}
public interface IVm
{
int StatusId { get; set; }
DateTime CreateDate { get; set; }
string Name { get; }
}
public class StatusViewModel : IVm
{
public DateTime CreateDate { get; set; }
public int StatusId { get; set; }
public string Name { get { return "StatusViewModel"; } }
}
public class MroViewModel : IVm
{
public DateTime CreateDate { get; set; }
public int StatusId { get; set; }
public string Name { get { return "MroViewModel"; } }
}
public enum VmKind {Status, Mro }
#region Strategy
public interface IDataGetter
{
IEnumerable<IVm> Get(VmKind vmKind);
}
public class MyDataService : IDataGetter {
public IEnumerable<IVm> Get(VmKind vmKind)
{
switch (vmKind)
{
case VmKind.Status:
return GetStatuses();
//break;
case VmKind.Mro:
return GetMro();
//break;
default:
throw new ArgumentException("Unknown VM type");
}
}
private IEnumerable<IVm> GetMro()
{
return new List<MroViewModel> {
new MroViewModel { StatusId = -1, CreateDate = DateTime.Now },
new MroViewModel { StatusId = 2, CreateDate = DateTime.Now }
};
}
private IEnumerable<StatusViewModel> GetStatuses()
{
return new List<StatusViewModel> {
new StatusViewModel { StatusId = -1, CreateDate = DateTime.Now },
new StatusViewModel { StatusId = 2, CreateDate = DateTime.Now }
};
}
}
#endregion
#region Factory
public class VmFactory {
static IVm Create(VmKind vmKind)
{
IVm result = null;
switch (vmKind)
{
case VmKind.Status:
result = new StatusViewModel { StatusId = -1, CreateDate = DateTime.Now };
break;
case VmKind.Mro:
result = new MroViewModel { StatusId = -1, CreateDate = DateTime.Now };
break;
default:
throw new ArgumentException("Unknown VM type");
//break;
}
return result;
}
}
#endregion
I didn't actually use the Factory here, but you could do it for easy VM creation.
I have tried a lot but all in vain.
I have written a LINQ code but not able to save changes in database.
It is giving no error neither it is updating record.
class Program
{
[Table(Name = "mainframe_replication")]
public class mainframe_replication
{
private string _REPL_GUID;
[Column(IsPrimaryKey = true, Storage = "_REPL_GUID")]
public string REPL_GUID
{
get { return this._REPL_GUID; }
set { this._REPL_GUID = value; }
}
private string _REPL_TYPE;
[Column(Storage = "_REPL_TYPE")]
public string REPL_TYPE
{
get { return this._REPL_TYPE; }
set { this._REPL_TYPE = value; }
}
private string _RPT_ID;
[Column(Storage = "_RPT_ID")]
public string RPT_ID
{
get { return this._RPT_ID; }
set { this._RPT_ID = value; }
}
private string _RPT_VERS;
[Column(Storage = "_RPT_VERS")]
public string RPT_VERS
{
get { return this._RPT_VERS; }
set { this._RPT_VERS = value; }
}
private string _RPT_BYTES;
[Column(Storage = "_RPT_BYTES")]
public string RPT_BYTES
{
get { return this._RPT_BYTES; }
set { this._RPT_BYTES = value; }
}
private string _REPL_DTM;
[Column(Storage = "_REPL_DTM")]
public string REPL_DTM
{
get { return this._REPL_DTM; }
set { this._REPL_DTM = value; }
}
private string _NOTIF_ID;
[Column(Storage = "_NOTIF_ID")]
public string NOTIF_ID
{
get { return this._NOTIF_ID; }
set { this._NOTIF_ID = value; }
}
}
public class MyPoco
{
public string ReportId { get; set; }
public string Reportversion { get; set; }
public string ReportBytes { get; set; }
public string ReportDate { get; set; }
public string NotifId { get; set; }
public string RecipAdd { get; set; }
}
public static string loglocation;
static void Main(string[] args)
{
try
{
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
Table<NOTIF_RECIP> NOTIF_RECIP_alias = db.GetTable<NOTIF_RECIP>();
Table<NOTIF_SCHED> NOTIF_SCHED_alias = db.GetTable<NOTIF_SCHED>();
Table<mainframe_replication> mainframe_replication_alias = db.GetTable<mainframe_replication>();
var ids = NOTIF_SCHED_alias.Select(x => x.NOTIF_RPT_ID).ToArray();
foreach (string notif_sched_data in ids)
{
var repljoinmf = mainframe_replication_alias
.Join(NOTIF_RECIP_alias, mfr => mfr.RPT_ID, nr => nr.NOTIF_RECIP_ID, (mfr, nr)
=> new MyPoco { ReportId = mfr.RPT_ID, Reportversion = mfr.RPT_VERS, ReportBytes = mfr.RPT_BYTES.ToString(), ReportDate = mfr.REPL_DTM.ToString(), NotifId = mfr.NOTIF_ID, RecipAdd = nr.NOTIF_RECIP_ADDR });
foreach (var repljoinmf_data in repljoinmf)
{
repljoinmf_data.NotifId = "abc";
//DO STUFF
// repljoinmf_data.NotifId = "Changedxyz";
}
db.SubmitChanges();
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
}
It is not giving any error while submitting changes.
What I need to change?
Any suggestion will be helpful.
If you want to save your changes back to the original data source, you need to be working with the actual entities instead of projections of those entities. Since you are joining two tables, one option is to put those instances into an anonymous type and update them:
foreach (string notif_sched_data in ids)
{
var repljoinmf = mainframe_replication_alias
.Join(NOTIF_RECIP_alias,
mfr => mfr.RPT_ID,
nr => nr.NOTIF_RECIP_ID,
(mfr, nr) => new {mfr, nr});
foreach (var repljoinmf_data in repljoinmf)
{
//DO STUFF
repljoinmf_data.mfr.NotifId = "Changedxyz";
}
db.SubmitChanges();
In your previous question you were told that anonymous types cannot be uptated, but in this case you're modifying instances that are referenced by the anonymous type. So you're not updating the anonymous type itself, just the objects that the anonymous type references.
You are modifying the property of your MyPoco object. This is just a representation of your table. That's why the database is not updated.
You can send your MyPoco to your client. It will perform some changes. Then you can recreate the entity and copy the properties from the Poco object. Then, you need to attach the modified entity to your table and then save the changes.
If you modify directly the entity, there is no need to attach, since it will have kept the links to the database (assuming you do that with the same Databasecontext).
I have the following model:
Base class:
public abstract class Identifiable{
private ObjectId id;
private string name;
protected Identifiable(){
id = ObjectId.GenerateNewId();
}
[BsonId]
public ObjectId Id{
get { return id; }
set { id = value; }
}
[BsonRequired]
public string Name{
get { return name; }
set { name = value; }
}
}
The name is unique.
A channel class
public class Channel : Identifiable{
private DateTime creationDate;
private string url;
private DailyPrograming dailyPrograming;
public DailyPrograming DailyPrograming{
get { return dailyPrograming; }
set { dailyPrograming = value; }
}
public DateTime CreationDate{
get { return creationDate; }
set { creationDate = value; }
}
public string Url{
get { return url; }
set { url = value; }
}
}
Daily programs. The name property is the date stored as ddMMyyyy:
public class DailyPrograming : Identifiable{
public DailyPrograming(){
DailyPrograms = new List<Program>(30);
}
public IList<Program> DailyPrograms { get; set; }
}
The programs:
public class Program : Identifiable{
private DateTime programDate;
private string category;
private string description;
public DateTime ProgramDate{
get { return programDate; }
set { programDate = value; }
}
public string Category{
get { return category; }
set { category = value; }
}
public string Description{
get { return description; }
set { description = value; }
}
}
Now, I want to filter the program of certain channel for specific date using:
public DailyPrograming GetProgramsForDate(string channelId, string prgDate){
ObjectId id = new ObjectId(channelId);
IMongoQuery query = Query.And(Query<Channel>.EQ(c => c.Id, id),
Query<DailyPrograming>.EQ(dp => dp.Name, prgDate));
var result = Database.GetCollection<DailyPrograming>(CollectionName).Find(query).FirstOrDefault();
return result;
}
But it never returns the existing data. How to retrieve the programings of a channel for a date?
-
var builder = Builders<BsonDocument>.Filter;
var filt = builder.Eq("Price", "9.20")
& builder.Eq("ProductName", "WH-208");
var list = await collection.Find(filt).ToListAsync();
We can use & instead of $and. See this post, for another example.
According to your sample I used id = "54c00c65c215161c7ce2a77c" and prgDate = "2212015"
then I changed the query to this:
var collection = database.GetCollection<Channel>("test6");
var id = new ObjectId("54c00c65c215161c7ce2a77c");
var query = Query.And(Query<Channel>.EQ(c => c.Id, id), Query<Channel>.EQ(c => c.DailyPrograming.Name, "2212015"));
var result = collection.Find(query).FirstOrDefault();
this query works fine
Some point:
Your collection type is Chanel not DailyPrograming
When your collection is Chanel you have to use Query<Channel> and query nested DailyPrograming via Query<Channel>.EQ(c => c.DailyPrograming.Name, "2212015")
I have such a funny question.
I have the following architecture:
For example, Manager class is implemented like this:
public sealed class Manager : Interface.Abstract.Employee
{
private Interface.IEmployee chief = null;
private readonly Decimal bonuslimit = Convert.ToDecimal(0.4F * Convert.ToSingle(BaseSalary));
public Manager(Person person, DateTime hiredate)
: base(person, hiredate)
{
}
public override List<Interface.IEmployee> Subordinates
{
get;
set;
}
public override Interface.IEmployee Chief
{
get
{
return this.chief;
}
set
{
//if(value is Associate)
//{
// throw new SystemException("Associate can't be a chief");
//}
this.chief = value;
}
}
public override Decimal Salary
{
get
{
var actualbonus = Convert.ToDecimal(0.01F * Convert.ToSingle(this.YearsSinceHired * BaseSalary));
var bonus = (actualbonus > bonuslimit) ? bonuslimit : actualbonus;
var additional = 0M;
if(this.HasSubordinates)
{
foreach(Interface.Abstract.Employee employee in this.Subordinates)
{
if(employee is Sales)
{
additional += employee.Salary;
}
}
}
return Convert.ToDecimal(Convert.ToSingle(additional) * 0.005F) + BaseSalary + bonus;
}
}
}
And 'factory client' that looks like this:
public class EmployeeFactoryClient
{
private IDictionary<String, IEmployee> employees = new Dictionary<String, IEmployee>();
public EmployeeFactoryClient()
{
this.Factory = new EmployeeFactory();
}
public EmployeeFactoryClient(IEmployeeFactory factory)
{
this.Factory = factory;
}
public IEmployeeFactory Factory { get; set; }
public void HireEmployee(Person person, String type, String code)
{
this.employees.Add(
new KeyValuePair<String, IEmployee>(
code,
this.Factory.Create(person, type, DateTime.Now)
)
);
}
public void DismissEmployee(String code)
{
this.employees.Remove(code);
}
public IEmployee GetEmployee(String code)
{
return this.employees[code];
}
public IEmployee this[String index]
{
get { return this.employees[index]; }
private set { this.employees[index] = value; }
}
public Decimal TotalSalary
{
get
{
var result = 0M;
foreach(var item in this.employees)
{
result += item.Value.Salary;
}
return result;
}
}
}
And finally I have some test code:
public void SalaryTest()
{
#region [Persons]
var SalesPerson01 = new Person
{
Birthday = new DateTime(1980, 11, 03),
Forename = "Corey",
Surname = "Black",
Gender = SexType.Female
};
var SalesPerson02 = new Person
{
Birthday = new DateTime(1980, 11, 03),
Forename = "John",
Surname = "Travis",
Gender = SexType.Male
};
#endregion
this.company.HireEmployee(SalesPerson01, "Sales", SalesPerson01.GetHashCode().ToString());
((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).YearsSinceHired = 10;
this.company.HireEmployee(SalesPerson02, "Sales", SalesPerson02.GetHashCode().ToString());
((Employee)this.company[SalesPerson02.GetHashCode().ToString()]).YearsSinceHired = 3;
///////////////////////////////////////////////////////////////////
((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).Subordinates.Add(
this.company[SalesPerson02.GetHashCode().ToString()]
);
Assert.AreEqual(1405M, this.company.TotalSalary);
}
Line
((Employee)this.company[SalesPerson01.GetHashCode().ToString()]).Subordinates.Add(this.company[SalesPerson02.GetHashCode().ToString()]); throws NullReferenceExeption. In the this.company[SalesPerson02.GetHashCode().ToString()] indexer returns IEmployee interface but not a class instance. Am I right? And if it is so how do I fix that?
I don't see anywhere that you are initializing the Subordinates member, so I suspect that it still has the default value which is null (not the empty list). The fix is to initialize it to an empty list in the constructor:
public Manager(Person person, DateTime hiredate) : base(person, hiredate)
{
Subordinates = new List<Interface.IEmployee>();
}
it seems you're putting in Person but then casting to Employee which are unrelated classes
indexer returns IEmployee interface but not a class instance. Am I right?
You don't right indexer must return instance, create instance from interface impossible.
I think this.company[SalesPerson02.GetHashCode().ToString()] returns null cause you don't add SalesPerson02 instance to your company object.