I am working on a C# application which consists of objects Department, Course, and Section. Each Department has many Courses, and each Course has many Sections. Currently I have three classes: Department, Course, and Section. Department contains some properties and then a List Courses, which contains the courses the department offers. Course contains some properties and then a List Sections, which contains the sections of the course. Is this a good way to have the code structured or should I be doing it a different way?
Secondly, when I instantiate a department in my application, I set some properties and then would like to begin adding courses to the List Courses defined in the Department class. However, I seem to be unable to simply do Department.Courses.Add(Course) from the application. What must I do within the Department class so that I may add objects to that list without breaking the principle of encapsulation?
An example of what I have with the list right now is:
class Department
{
// ......
List<Course> Courses = new List<Course>;
}
however Department.Courses is not available in the program code after the class has been instantiated (all other properties of the class are available).
Instantiate the internal Courses list inside the parameterless constructor of your class.
private List<Course> _coursesList;
public Department()
{
_coursesList = new List<Course>();
}
Also, another way to ensure the encapsulation is to provide a method on your Department class to add the courses to it instead of directly exposing the courses list. Something like
public void AddCourse(Course c) { ... }
// or (adding the feature of doing the method calls in a composable way)
public Course AddCourse(Course c) { ... }
// or
public void AddCource(String name, etc) { ... }
I think in your case it is not a good idea do directly exposes the List because the class List, may provide methods like, Add and Remove which could potentially creates an invalid state on your parent class. So if you choose to expose methods to manipulate the internal collections like I suggested, you could expose an array of Courses to your API clients (remember the arrays are read-only) so your API consumers won't be able to the create side effects on your department class.
public Course[] Courses {
get { return _coursesList.ToArray(); }
}
In addition, you could also implement the IEnumerable interface on your Department class. It would enable you to take advantage of the all LINQ extension methods available in C# 3.0.
I hope it helps,
Carlos.
Probably something Similar. There are several ways of soing this. depends upon what your requirements are.
public class Department
{
// Initialize the list inside Default Constructor
public Department()
{ courses = new List<Course>(); }
// Initialize List By Declaring outside and Passing with Dpartment Initilization
public Department(List<Course> _courses)
{ courses = _courses; }
List<Course> courses;
public List<Course> Courses
{
get
{
if (courses == null)
return new List<Course>();
else return courses;
}
set { courses = value; }
}
internal bool AddCourseToCourses(Course _course)
{
bool isAdded = false;
// DoSomeChecks here like
if (!courses.Contains(_course))
{
courses.Add(_course);
isAdded = true;
}
return isAdded;
}
}
public class Course
{
public Course(List<Subject> _subject)
{ subjects = _subject; }
List<Subject> subjects;
public List<Subject> Subjects
{
get { return subjects; }
set { subjects = value; }
}
}
// I do not get what do you mean by course "section", very general.
// used Subject instead, Change as you want just to give an idea
public class Subject
{
string name;
public string Name
{
get { return name; }
set { name = value; }
}
int creditHours;
public int CreditHours
{
get { return creditHours; }
set { creditHours = value; }
}
public Subject(string _name, int _creditHours)
{
name = _name;
creditHours = _creditHours;
}
}
public class TestClass
{
public void DoSomething()
{
// Subjects
Subject subj1 = new Subject("C#", 10);
Subject subj2 = new Subject(".Net", 10);
// List of Subjects
List<Subject> advancedPrSubjects = new List<Subject>();
advancedPrSubjects.Add(subj1);
advancedPrSubjects.Add(subj2);
// Course
Course advancedProgramming = new Course(advancedPrSubjects);
// Deliver authoroty to add Course to Department Class itself
Department dept = new Department();
dept.AddCourseToCourses(advancedProgramming);
}
}
There are better ways of doing this. have a look at these tutorials for better insight
http://www.csharp-station.com/Tutorials/Lesson07.aspx
http://www.functionx.com/csharp/index.htm
Hope it helps
As to your second question - without some code or more details its a bit hard - but i'll take a guess.
You're probably not actually creating the list, just declaring it
List<xxxx> _variable;
vs
List<xxxx> _variable = new List<xxxxx>();
You must create a list to be able to add to it (new List());
You sound as if you're on the right track.
Your second problem could be down to many things.
It could be as Ruddy says and that you're not creating the list.
It could also be that your Courses List is not public or that you haven't instanciated a new Course object to add.
Related
This is homework!!! Please do not interpret this as me asking for someone to code for me.
My Program: http://pastebin.com/SZP2dS8D
This is my first OOP. The program works just fine without user input(UI), but the implementation of it renders my design partially ineffective. I am not using a List collection because of assignment restrictions. My main goal is to have everything running from the Transcript class. Here are some issues I am running into:
Allowing the user to add new course without having to create a new instance of Transcript
each time
Associating the Courses added to a specific Quarter
Here is some pseudo code to show what I am trying to accomplish. I have been experimenting with it, but have yet to succeed.
Please enter the quarter: (user input)
Would you like to add a course?
while (true)
Enter Course/Credits/Grade
//new Course information populated with user input
transcript.AddCourse.to specific Quarter((Fall 2013) new Course("Math 238", 5, 3.9));
transcript.AddCourse.to specific Quarter((Fall 2013) new Course("Phys 223", 5, 3.8));
transcript.AddCourse.to specific Quarter((Fall 2013) new Course("Chem 162", 5, 3.8));
MY QUESTION[S]: Should I keep the Transcript class, or discard it? With the current functionality of creating a new course, is it possible to keep it this way while using UI, or do I need to head back to the chalk board and reconfigure?
Hopefully this is coherent and not too broad. If clarification is needed please ask and I will me more than happy to provide more details.
I would consider the following compositon
public class Transcript
{
public Quarter[] Quarters{get;set;}
}
public class Quarter
{
public Course[] Courses{get;set;}
}
You only need one instance of the transcript class.
This will enable you to model n quarters (multiple years) with n courses per quarter.
In your input loop you can add new courses/quarters in response to user input
There are a lot of ways to model this problem and I think you're right to have a transcript class, but instead of thinking that a quarter has a set of courses I would suggest that which quarter a course is offered is a property of the course. For example:
public class Transcript
{
private List<Course> courses_ = new List<Course>();
public IEnumerable<Course> Courses {get { return courses_; }
public IEnumerable<Course> GetCoursesFor(int year, int quarter)
{
return courses_.Where(course => course.Year == year && course.Quarter == quarter);
}
public void AddCourse(Course course)
{
courses_.Add(course);
}
}
public class Course
{
public int Year {get; private set;}
public int Quarter {get; private set;}
// ... other members
}
you can try this
public enum Quarters
{
First,
Second,
Third,
Fourth
}
class Courses
{
private Quarters ThisQuarter { get; private set; }
private List<Tuple<Quarters, List<Courses>>> SchoolProgram = new List<Tuple<Quarters, List<Courses>>>();
public int year { get; private set; }
public string name { get; private set; }
private Courses()
{
//load list from database or xml
//each tuple has one quarters and a list
// of associated courses
//SchoolProgram.Add(new Tuple<Quarters, List<Courses>>(Quarters.First, new List<Courses>(){new Courses(2010,"Math",Quarters.First),
// new Courses(2010,"English",Quarters.First),
// new Courses(2010,"Physics",Quarters.First)}));
}
public Courses(int year,string name,Quarters q)
{
this.year = year;
this.name = name;
ThisQuarter = q;
}
public Courses GetCourse()
{
return SchoolProgram.Find(q => q.Item1 == ThisQuarter).Item2.Single(c => (c.year == this.year && c.name == this.name));
}
}
public class Transcript
{
private List<Courses> SchoolProgram = new List<Courses>();
public Transcript()
{
//maybe aditional logic here
}
public void AddCourse(int year,string name,Quarters q)
{
Courses c = new Courses(year, name, q);
SchoolProgram.Add(c.GetCourse());
}
}
you can add additional logic about the grades and other stuff....best wishes
I am using Domain Service to fetch data from database from Silverlight Client.
In DomainService1.cs, I have added the following:
[EnableClientAccess()]
public class Product
{
public int productID;
public string productName;
public List<Part> Parts = new List<Part>(); //Part is already present in Model designer
}
In DomainService1 class I added a new method to retrive a collection of the custom class object:
[EnableClientAccess()]
public class DomainService1 : LinqToEntitiesDomainService<HELPERDBNEWEntities1>
{
...
public List<Product> GetProductsList(...)
{
List<Product> resultProducts = new List<Product>();
...
return resultProducts;
}
}
From the silverlight client I am trying to access that method:
DomainService1 ds1 = new DomainService1();
var allproductList = ds1.GetProductsList(...);
ds1.Load<SLProduct>(allproductList).Completed += new EventHandler(Load_Completed); //Not correct usage
However it is not the correct way to call the new method. The reason I added a new class Product in DomainServices.cs is to have an efficient grouping. I cannot achieve the same using the model classes auto-generated by the entity framework.
How call I call the new method from the client?
I believe there is a similar question with an answer here:
Can a DomainService return a single custom type?
Also, here is some discussion about the overall problem of adding custom methods in a Domain Service:
http://forums.silverlight.net/t/159292.aspx/1
While I don't know what you mean by "it is not the correct way to call the new method", or if you're getting any errors, I thought maybe posting some working code might help.
My POCO
public class GraphPointWithMeta
{
[Key]
public Guid PK { get; set; }
public string SeriesName { get; set; }
public string EntityName { get; set; }
public double Amount { get; set; }
public GraphPointWithMeta(string seriesName, string entityName, double amount)
{
PK = Guid.NewGuid();
SeriesName = seriesName;
EntityName = entityName;
Amount = amount;
}
// Default ctor required.
public GraphPointWithMeta()
{
PK = Guid.NewGuid();
}
}
A method in the domain service (EnableClientAccess decorates the class)
public IEnumerable<GraphPointWithMeta> CallingActivityByCommercial()
{
List<GraphPointWithMeta> gps = new List<GraphPointWithMeta>();
// ...
return gps;
}
Called from the Silverlight client like
ctx1.Load(ctx1.CallingActivityByCommercialQuery(), CallingActivityCompleted, null);
client call back method
private void CallingActivityCompleted(LoadOperation<GraphPointWithMeta> lo)
{
// lo.Entities is an IEnumerable<GraphPointWithMeta>
}
I am not sure if your Product class is an actual entity or not. From the way it is defined, it does not appear to be an entity. My answer is assuming it is not an entity. You will need to apply the DataMemberAttribute for your Product properties, and you wouldn't load the product list - load is for Entity Queries (IQueryable on the service side). You would just invoke it like this (client side):
void GetProductList( Action<InvokeOperation<List<Product>>> callback)
{
DomainService ds1 = new DomainService();
ds1.GetProductsList(callback, null);//invoke operation call
}
And the domain service's (server side) method needs the InvokeAttribute and would look like this:
[EnableClientAccess]
public class MyDomainService
{
[Invoke]
public List<Product> GetProductList()
{
var list = new List<Product>();
...
return list;
}
}
And here is how your Product class might be defined (if it is not an entity):
public class Product
{
[DataMember]
public int productID;
[DataMember]
public string productName;
[DataMember]
public List<Part> Parts = new List<Part>(); // you might have some trouble here.
//not sure if any other attributes are needed for Parts,
//since you said this is an entity; also not sure if you
//can even have a list of entities or it needs to be an
//entity collection or what it needs to be. You might
//have to make two separate calls - one to get the products
//and then one to get the parts.
}
Like I said, i am not sure what Product inherits from... Hope this helps.
I've written myself a nice simple little domain model, with an object graph that looks like this:
-- Customer
-- Name : Name
-- Account : CustomerAccount
-- HomeAddress : PostalAddress
-- InvoiceAddress : PostalAddress
-- HomePhoneNumber : TelephoneNumber
-- WorkPhoneNumber : TelephoneNumber
-- MobilePhoneNumber : TelephoneNumber
-- EmailAddress : EmailAddress
This structure is completely at odds with the legacy database I'm having to work with, so I've defined a flat DTO which contains the data for each element in the customer graph - I have views and stored procedures in the database which allow me to interact with the data using this flat structure in both directions, this all works fine & dandy :)
Flattening the domain model into a DTO for insert/update is straightfoward, but what I'm having trouble with is taking a DTO and creating the domain model from it... my first thought was to implement a visitor which would visit each element in the customer graph, and inject values from the DTO as necessary, something a bit like this:
class CustomerVisitor
{
public CustomerVisitor(CustomerDTO data) {...}
private CustomerDTO Data;
public void VisitCustomer(Customer customer)
{
customer.SomeValue = this.Data.SomeValue;
}
public void VisitName(Name name)
{
name.Title = this.Data.NameTitle;
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
}
// ... and so on for HomeAddress, EmailAddress etc...
}
That's the theory and it seems like a sound idea when it's laid out simply like that :)
But for this to work the entire object graph would need to be constructed before the visitor erm, visited, otherwise I'd get NRE's left right and centre.
What I want to be able to do is let the visitor assign objects to the graph as it visits each element, with the goal being to utilize the Special Case pattern for objects where data is missing in the DTO, eg.
public void VisitMobilePhoneNumber(out TelephoneNumber mobileNumber)
{
if (this.Data.MobileNumberValue != null)
{
mobileNumber = new TelephoneNumber
{
Value = this.Data.MobileNumberValue,
// ...
};
}
else
{
// Assign the missing number special case...
mobileNumber = SpecialCases.MissingTelephoneNumber.Instance;
}
}
Which I honestly thought would work, but the C# throws me an error on:
myVisitor.VisitHomePhone(out customer.HomePhoneNumber);
Since you can't pass ref/out parameters in this way :(
So I'm left with visiting independent elements and reconstructing the graph when its done:
Customer customer;
TelephoneNumber homePhone;
EmailAddress email;
// ...
myVisitor.VisitCustomer(out customer);
myVisitor.VisitHomePhone(out homePhone);
myVisitor.VisitEmail(out email);
// ...
customer.HomePhoneNumber = homePhone;
customer.EmailAddress = email;
// ...
At this point I'm aware that I'm quite far away from the Visitor Pattern and am much closer to a Factory, and I'm starting to wonder whether I approached this thing wrong from the start..
Has anyone else run into a problem like this? How did you overcome it? Are there any design patterns which are well suited to this scenario?
Sorry for posting such a looong question, and well done for reading this far :)
EDIT In response to the helpful answers from Florian Greinacher and gjvdkamp, I settled on a relatively simple factory implementation that looks like this:
class CustomerFactory
{
private CustomerDTO Data { get; set; }
public CustomerFactory(CustomerDTO data) { ... }
public Customer CreateCustomer()
{
var customer = new Customer();
customer.BeginInit();
customer.SomeFoo = this.Data.SomeFoo;
customer.SomeBar = this.Data.SomeBar
// other properties...
customer.Name = this.CreateName();
customer.Account = this.CreateAccount();
// other components...
customer.EndInit();
return customer;
}
private Name CreateName()
{
var name = new Name();
name.BeginInit();
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
// ...
name.EndInit();
return name;
}
// Methods for all other components...
}
I then wrote a ModelMediator class to handle interaction between the data layer and the domain model...
class ModelMediator
{
public Customer SelectCustomer(Int32 key)
{
// Use a table gateway to get a customer DTO..
// Use the CustomerFactory to construct the domain model...
}
public void SaveCustomer(Customer c)
{
// Use a customer visitor to scan for changes in the domain model...
// Use a table gateway to persist the data...
}
}
I think you are really over-complicating things here. Just use a factory method and let your domain objects clearly state on which other domain objects they depend.
class Customer
{
private readonly Name name;
private readonly PostalAddress homeAddress;
public Customer(Name name, PostalAddress homeAddress, ...)
{
this.name = name;
this.homeAddress = homeAddress;
...
}
}
class CustomerFactory
{
Customer Create(CustomerDTO customerDTO)
{
return new Customer(new Name(...), new PostalAdress(...));
}
}
If you need to take a dependency from Customer to CustomerDTO pass the DTO as additional argument to the constructor, probably wrapped in an additional abstraction.
This way things will keep clean, testable and easy to understand.
I don't think i would go with a visitor. That would be appropriate if you don't know at design time, what operations you need to perform on it later, so you open up the class to allow for others to write visitors that implement that logic. Or there are so many things that you need to do on it that you don't want to clutter your class with this.
What you want to do here is create an instance of a class from a DTO. Since the structure of the class and the DTO are closely linked (you do your mapping in the DB, I assume you handle all mapping issues on that side and have a DTO format that maps directly to the structure of your customer), you know at design time what you need to. There's no need for much flexibility. (You want to be robust though, that the code can handle changes to the DTO, like new fields, without throwing exceptions)
Basically you want to construct a Customer from a snippet of a DTO. What format do you have, just XML or something else?
I think I would just go for a constructor that accepts the DTO and returns a Customer (example for XML:)
class Customer {
public Customer(XmlNode sourceNode) {
// logic goes here
}
}
The Customer class can 'wrap around' an instance of the DTO and 'become one'. This allows you to very naturally project an instance of your DTO into a customer instance:
var c = new Customer(xCustomerNode)
This handles the high level pattern choice. Do you agree so far?
Here's a stab at the specific issue you mention with trying to pass properties 'by ref'.I do see how DRY and KISS can be at odds there, but I would try not to overthink it. A pretty straight forward solution could fix that.
So for the PostalAddress, it would have it's own constructor too, just like the Customer itself:
public PostalAddress(XmlNode sourceNode){
// here it reads the content into a PostalAddress
}
on the customer:
var adr = new PostalAddress(xAddressNode);
The problem I see here is, where do you put the code that figures out if this if the InvoiceAddress or the HomeAddress? This does not belong in the constructor of the PostalAddress, because there could be other uses for the PostalAddress later, you don't want to hardcode it in the PostalAddress class.
So that task should be handled in the Customer class. This is where he usage of the PostalAddress is determined. It needs to be able to tell from the returned Address what type of address it is. I guess the simplest approach would be to just add a property on PostalAddress that tells us:
public class PostalAddress{
public string AdressUsage{get;set;} // this gets set in the constructor
}
and in the DTO just specify it:
<PostalAddress usage="HomeAddress" city="Amsterdam" street="Dam"/>
Then you can look at it in the Customer class and 'stick it' in the right property:
var adr = new PostalAddress(xAddressNode);
switch(adr.AddressUsage){
case "HomeAddress": this.HomeAddress = adr; break;
case "PostalAddress": this.PostalAddress = adr; break;
default: throw new Exception("Unknown address usage");
}
A simple attribute that tells the Customer what type of address it is would be enough I guess.
How does it sound so far? Code below puts it all together.
class Customer {
public Customer(XmlNode sourceNode) {
// loop over attributes to get the simple stuff out
foreach (XmlAttribute att in sourceNode.Attributes) {
// assign simpel stuff
}
// loop over child nodes and extract info
foreach (XmlNode childNode in sourceNode.ChildNodes) {
switch (childNode.Name) {
case "PostalAddress": // here we find an address, so handle that
var adr = new PostalAddress(childNode);
switch (adr.AddressUsage) { // now find out what address we just got and assign appropriately
case "HomeAddress": this.HomeAddress = adr; break;
case "InvoiceAddress": this.InvoiceAddress = adr; break;
default: throw new Exception("Unknown address usage");
}
break;
// other stuff like phone numbers can be handeled the same way
default: break;
}
}
}
PostalAddress HomeAddress { get; private set; }
PostalAddress InvoiceAddress { get; private set; }
Name Name { get; private set; }
}
class PostalAddress {
public PostalAddress(XmlNode sourceNode) {
foreach (XmlAttribute att in sourceNode.Attributes) {
switch (att.Name) {
case "AddressUsage": this.AddressUsage = att.Value; break;
// other properties go here...
}
}
}
public string AddressUsage { get; set; }
}
class Name {
public string First { get; set; }
public string Middle { get; set; }
public string Last { get; set; }
}
and a snippet of XML. You haven't said anything about your DTO format, would work for other formats too.
<Customer>
<PostalAddress addressUsage="HomeAddress" city="Heresville" street="Janestreet" number="5"/>
<PostalAddress addressUsage="InvoiceAddress" city="Theresville" street="Hankstreet" number="10"/>
</Customer>
Regards,
Gert-Jan
For doing conversions between a model class and a DTO, my preference is to do one of four things:
a. use an implicit conversion operator (especially when dealing json-to-dotnet transitions).
public class Car
{
public Color Color {get; set;}
public int NumberOfDoors {get; set;}
}
public class CarJson
{
public string color {get; set;}
public string numberOfDoors { get; set; }
public static implicit operator Car(CarJson json)
{
return new Car
{
Color = (Color) Enum.Parse(typeof(Color), json.color),
NumberOfDoors = Convert.ToInt32(json.numberOfDoors)
};
}
}
and then usage is
Car car = Json.Decode<CarJson>(inputString)
or more simply
var carJson = new CarJson {color = "red", numberOfDoors = "2"};
Car car = carJson;
voila, instant conversion :)
http://msdn.microsoft.com/en-us/library/z5z9kes2.aspx
b. Use linq projection to change the shape of the data
IQueryable<Car> cars = CarRepository.GetCars();
cars.Select( car =>
new
{
numberOfDoors = car.NumberOfDoors.ToString(),
color = car.Color.ToString()
} );
c. Use some combination of the two
d. Define an extension method (that could also be used in the linq projection)
public static class ConversionExtensions
{
public static CarJson ToCarJson(this Car car)
{
return new CarJson {...};
}
}
CarRepository.GetCars().Select(car => car.ToCarJson());
You could take the approch I described here: convert a flat database resultset into hierarchical object collection in C#
The idea behind is to read an object, like Customer and put it into a Dictionary. When reading the data for e.g. CustomerAccount, you can now take the Customer from the Dictionary and add the Customer Account to the customer.
You'll have only one iteration over all data to build your object graph.
I am working on a program that uses Nhibernate to persist objects, and Xml Serialization to import and export data. I can't use the same properties for collections as, for example, Nhibernate needs them to be Ilists, because it has it's own implementation of that interface, and I can't Serialize interfaces. But as I need both properties to be synchronized, I thought I could use two different properties for the same Field. The properties will be according to what I need for each framework, and they will update the Field accrodingly.
So, I have the following field:
private IList<Modulo> modulos;
And the following properties:
[XmlIgnore]
public virtual IList<Modulo> Modulos
{
get { return modulos; }
set { modulos = value; }
}
[XmlArray]
[XmlArrayItem(typeof(Modulo))]
public virtual ArrayList XmlModulos
{
get
{
if (modulos == null) return new ArrayList();
var aux = new ArrayList();
foreach (Modulo m in modulos)
aux.Add(m);
return aux;
}
set
{
modulos = new List<Modulo>();
foreach (object o in value)
modulos.Add((Modulo)o);
}
}
The first one is working perfectly, being quite standard, but I have some problems with the second one. The get is working great as I am having no problems Serializing objects (meaning it correctly takes the info from the field). But when I need to Deserialize, it is not getting all the info. The debugger says that after the Deserialization, the field is not updated (null) and the Property is empty (Count = 0).
The obvious solution would be using two unrelated properties, one for each framework, and passing the information manually when needed. But the class structure is quite complicated and I think there should be a more simple way to do this.
Any Idea how I can modify my property for it to do what I want? Any help will be appreciated.
The short answer is that you cant.
Typically you would create a DTO ( Data transfer object ) separate from your NHibernate objects. For example:
public class PersonDto
{
[XmlAttribute(AttributeName = "person-id")]
public int Id { get; set; }
[XmlAttribute(AttributeName = "person-name")]
public string Name{ get; set; }
}
On your DTO object you only put the properties that you intend to serialize. You than create a DTO from your domain model when you need to serialize one.
There is a great little library called automapper that makes mapping from your domain objects to your dto's pretty straight forward. See: http://automapper.codeplex.com/
Here is an example of a person class that supports mapping to the above DTO.
public class Person
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
static Person()
{
Mapper.CreateMap<PersonDto, Person>();
Mapper.CreateMap<Person, PersonDto>();
}
public Person(PersonDto dto)
{
Mapper.Map<PersonDto, Person>(dto, this);
}
public PersonDto ToPersonDto()
{
var dto = new PersonDto();
Mapper.Map<Person, PersonDto>(this, dto);
return dto;
}
}
I'm new to LINQ and I've been at this for hours now. I have a List<> of objects where one of the objects properties is a List of selected categories. I also have, outside of the objects, a List representing a subset of categories and I want to return all objects which contain at least one category that is also in the subset as illustrated in the following pseudo code (not my actual code)
List<string> subset = cat, dog, mouse
List<myclass> myclasses =
{name:alphie, category:[cat,elephant]},{name:sally, category:[fish]}, {name:bob, category:[dog, mouse]}
In the above example I need to return alphie and bob since they both have at least one category that's in my subset.
The only solution so far is to get a list of both and then use expensive foreach loops to go through and compare. I'm sure LINQ must provide a more efficient way to achieve the same?
More details (I think my pseudo code is not detailed enough)
public class RadioProgram {
...
private List<string> _category = new List<string>();
public List<string> Category { get { return _category; } set { _category = value; } }
...
}
public class Category {
...
private string _categoryName = "";
private List<Category> _subCategories = new List<Category>();
public string CategoryName { get { return _categoryName; } set { _categoryName = value; } }
public List<Category> SubCategories { get { return _subCategories; } set { _subCategories = value; } }
...
}
I have a method, GetCategories(string parentCategory), that returns all child categoryNames as List. Each radioProgram.Category (yes, name needs to be refactored to plural) is itself a List and may contain zero, one or more categoryNames. I'm getting my master list of radioPrograms and I want to return a subset that contain where each one contains at least one categoryName that matches the set from GetCategories.
I'm trying to avoid changing the architecture of the application (which is a potential solution) as it means a lot of refactoring of existing functionality AND I think this happens to be a good exercise for tackling and understanding LINQ.
One thing you could use is
myclasses
.Where(o => o.category.Any(c => subset.Contains(c)));