How to design collection in C# - c#

I have a class MySet
class MySet
{
.......
}
This class will declare a reference to another type
(i.e)
class MySubSet
{
....
}
The purpose of the type MySubset is to supply "subset id" and a collection of integers to
the type MySet.
Which one of the followings is the correct implementation
(1)
class MySet
{
int mySetID;
MySubSet subset = new MySubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public MySubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
(2)
class MySet
{
int mySetID;
AnotherSubSet subset = new AnotherSubSet();
public int MySetID
{
get { return mySetID; }
set { mySetID = value; }
}
public AnotherSubSet MySubSet
{
get { return subset; }
set { subset = value; }
}
}
class AnotherSubSet : List<int>
{
int subsetID;
List<int> lst = new List<int>();
public int SubSetID
{
get { return subsetID; }
set { subsetID = value; }
}
}
If both are worst design consideration help me to implement the one that I could follow.

MySet doesn't look like a collection to me. It's just a class.
I'd rename it to ´MyEntity´or something like that.
List<MyEntity> mySet = new List<MyEntity>();

From all the information you've provided, I would do this:
public class MyEntity
{
public int ID { get; set; } // shortcut
public List<int> Numbers = new List<int> { get; set; } // shortcut
}
Sorry, I don't have /Net3.0 to hand so can't check the constructor of the list with the shortcut get/set but its the theory that counts...

The first version is better (as improved upon by ck) - use composition instead of inheritance. You are advised not to add properties to collections, which is effectively what you're doing in version 2. Collections should contain their items only. Someone else may be able to expand on the reasons for this, as I am not an expert, but it does cause serialization problems.

Number 2 is better, use inheritence not composition for this pattern, - because fundementally, it is a collection. It does not contain a collection. Inheritance gives you all the functionality of the base class without the need to write pass-through functions. If you want to add a new item to the collection, using composition, you either have to add a pass through method for the Add() method to class MySubSet:
class MySubSet
{
int subsetID;
List<int> subset = new List<int>();
public List<int> SubSet
{
get { return subset; }
set { subset = value; }
}
public void Add(int i) { subset.Add(i); } // pass through to subset.Add()
}
or you have to use the following non-intuitive and confusing syntax...
MySet.MySubSet.SubSet.Add(67);
with inheritence, all you need is
MySet.MySubSet.Add(67);

Related

EF CF - List<T> of Primitive Type

I have the following:
public class Broadcast {
public int NumUsersToMessage { get; set; }
public int NumMessagesQueued { get; set; }
public string DbUsersMessaged { get; set; }
public int NumMessagesSent {
get {
return UsersMessaged.Count();
}
}
public List<int> UsersMessaged {
get {
return DbUsersMessaged == null ? new List<int>() : DbUsersMessaged.Split(',').Select(Int32.Parse).ToList();
}
set {
DbUsersMessaged = value != null ? String.Join(",", value) : null;
}
}
}
My goal here is to only ever access DbUsersMessaged through UsersMessaged. I'm attempting to do broadcast.UsersMessaged.Add(2), however since this is not an assignment, I can't get the property to behave as I like. Instead, I have to do this:
tempList = broadcast.UsersMessaged();
tempList.Add(2);
broadcast.UsersMessaged = tempList;
db.SaveChanges();
Which is obviously unwieldy. I'm considering making an AddReassign extension method but I want to know - what's the standard practice here for supporting Lists of primitive types? It looks like even with the extension method, my best shot looks like this:
broadcast.UsersMessaged = broadcast.UsersMessaged.AddReassign(2) // yuck!
Before anyone asks - we've intentionally denormalized this for performance reasons.
If you don't care about performance, you can create own list:
public class MyList : IList<int>
{
private List<int> underlyingList;
private Broadcast entity;
public MyList(Broadcast entity)
{
this.entity = entity;
this.underlyingList = entity.DbUsersMessaged?.Split(",") ?? new List<int>();
}
public void Add(int i)
{
this.underlyingList.Add(i);
this.entity.DbUsersMessaged = String.Join(",", underylingList);
}
// other interface memebers impl
}
Then
MyList list;
public IList<int> UsersMessaged {
get {
return myList ?? (myList = new MyList(this));
}
}
Of course it is only sample.
I recommend you to have a look at this: Entity Framework 5 - Looking for Central Point to Execute Custom Code after Entity is Loaded from Database
And then convert from string to list, and then use Saving Changes event to convert back into the string construction when saving.
Then, for performance, maybe you want to use byte[] rather than a string for storing the data in the database.

Getting the Total Number of Elements From All Lists Belonging to An Object

I have been given some code that has objects composed of lists of different types. A simple example of what I mean:
public class Account
{
private long accountID;
private List<string> accountHolders;
private List<string> phoneNumbers;
private List<string> addresses;
public Account()
{
this.accountHolders = new List<string>();
this.phoneNumbers = new List<string>();
this.addresses = new List<string>();
}
public long AccountID
{
get
{
return this.accountID;
}
set
{
this.accountID = value;
}
}
}
For a requirement I need to get the total amount of elements in each list for validation purposes. I have the following method which works:
public class AccountParser
{
// Some code
public int CountElements(Account acct)
{
int count = 0;
count += acct.accountHolders.Count();
count += acct.phoneNumbers.Count();
count += acct.addresses.Count();
return count;
}
}
but was wondering if there was a better way to do this. I know I can enumerate over a List with Linq but I can't seem to get it to work in this case.
What you're doing is the right thing
You could do it in one line without declaring any variable
public int CountElements(Account acct)
{
return acct.accountHolders.Count() + acct.phoneNumbers.Count() + acct.addresses.Count();
}
But it doesn't change much.
The ammount of lists is static, because the class is static, so it doesn't make sense to use Reflection if the structure wont change.
Now you could have more than one Account classes with different types of lists. In that case, i would create an abstract AbsAccount class, that has an abstract CountElements property:
public abstract class AbsAccount
{
public abstract int CountElements { get; }
}
public class Account: AbsAccount
{
private List<string> accountHolders;
private List<string> phoneNumbers;
private List<string> addresses;
public override int CountElements
{
get
{
return this.accountHolders.Count()
+ this.phoneNumbers.Count()
+ this.addresses.Count();
}
}
}
public class AccountParser
{
// Some code
public int CountElements(AbsAccount acct)
{
return acct.CountElements;
}
}
But maybe im taking it too far...
You can add items to a list then call .Summethod on it, but it's not better from performance point of view.
public class AccountParser
{
// Some code
public int CountElements(Account acct)
{
List<string> all = new List<string>();
all.AddRange(acct.accountHolders);
all.AddRange(acct.phoneNumbers);
all.AddRange(acct.addresses);
return all.Count();
}
}
Another approach will be (because I can see you are not exposing directly your lists) to use observer pattern, and update the number of elements in another field or even list, every time you are updating one of your lists. Then get the value from that field, but I think the best way is the one you have already adopted.

Get access to my derived class members

I have several classes that inhabit from this class:
public abstract class Class1
{
private string _protocol;
private static List<Plus> _class1Objects;
public string Protocol
{
get { return _protocol; }
set { _protocol = value; }
}
public static List<Plus> Class1Objects
{
get { return _class1Objects; }
set { _class1Objects = value; }
}
}
And the derive class:
public class Class2 : Plus
{
public bool name;
public int id;
}
public Webmail(string name, int id)
{
if (Class1Objects == null)
Class1Objects = new List<class1>();
.....
Class1Objects.Add(this);
}
And after my list is full of Class1Objects:
for (int i = 0; i < Class1.Class1Objects.Count; i++)
{
if (Class1.Class1Objects[i].GetType() == typeof(Class2))
}
(Class2)Class1.Class1Objects[i].
}
}
Here after (Class2)Class1.Class1Objects[i]. i cannot see my Class2 memners
You need one additional paranthese:
((Class2)Class1.Class1Objects[i]).
At the moment it is read as the following:
(Class2)(Class1.Class1Objects[i].) //<= at the '.' it is still a class1
BUT as David said in his comment: If all are of type Class2 it should be a collection of that type and if not you should check the type, altogether with foreach:
foreach(var item in Class1.Class1Objects)
{
if(item is Class2)
((Class2)Class1.Class1Objects[i]).
}
It would be cleaner to use as:
for (int i = 0; i < Class1.Class1Objects.Count; i++)
{
var c2 = Class1.Class1Objects[i] as Class2;
if (c2!=null)
}
c2.<whatever was meant to come after the .>
}
}
You might also want to consider switching to foreach unless there's a specific reason you want to manually extract each element from the List, e.g. if you're actually storing new values back into the list.
The correct syntax would be:
((Class2)Class1.Class1Objects[i]).name;
Because in your case, when you type something like this:
(Class2)Class1.Class1Objects[i].name;
You try to access the member name of Class1.Class1Objects[i], and only after that you try to cast it to Class2.
Also, the whole loop would be much simpler if you used foreach:
using System.Linq;
foreach(Class2 c in Class1.Class1Objects.OfType<Class2>())
{
Console.WriteLine(c.name); // or whatever you need to do with it
}

How to make a arrayclass access with this[][]

I want to create an Matrix class for some calculations. At my research i was stumble over some performance discussions Array[,] vs Array[][] and they conclusion was always use Array[][] if you want it fast
When i'm trying to provide access to an value via [][] it seems like i miss something important because i cant create an property like this
public double this[int iRow][int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
my problem is the second [] because the following works well
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
So what do i need to add in this class to let it work with [][] ?
public class Matrix
{
private bool _isSquare;
private double[][] matrix;
public double this[int iRow,int iCol]
{
get { return matrix[iRow][iCol]; }
set { matrix[iRow][iCol] = value; }
}
}
You can't do this in one class.
var b = a[1][2];
is the same as
var temp = a[1];
var b = temp[2];
They are two separate indexing operations.
Your first indexer would need to return an instance of some class that also has an indexer.
Using Indexers (C#)
Not sure what you are trying to do but if your matrix was the following you could still do what you are looking for
public class M
{
public double[][] Matrix { get; private set; }
public M()
{
Matrix = new double[2][]{new double[2], new double[2]};
}
}
M n = new M();
n.Matrix[0][0] = 1.0;

How to compare two distinctly different objects with similar properties

This is all in C#, using .NET 2.0.
I have two lists of objects. They are not related objects, but they do have certain things in common that can be compared, such as a GUID-based unique identifier. These two lists need to be filtered by another list which just contains GUIDs which may or may not match up with the IDs contained in the first two lists.
I have thought about the idea of casting each object list to just object and sorting by that, but I'm not sure that I'll be able to access the ID property once it's cast, and I'm thinking that the method to sort the two lists should be somewhat dumb in knowing what the list to be sorted is.
What would be the best way to bring in each object list so that it can be sorted against the list with only the IDs?
You should make each of your different objects implement a common interface. Then create an IComparer<T> for that interface and use it in your sort.
Okay, if you have access to modify your original classes only to add the interface there, Matthew had it spot on. I went a little crazy here and defined out a full solution using 2.0 anonymous delegates. (I think I'm way addicted to 3.0 Lambda; otherwise, I probably would've written this out in foreach loops if I was using 2005 still).
Basically, create an interface with the common properties. Make yoru two classes implement the interface. Create a common list casted as the interface, cast and rip the values into the new list; remove any unmatched items.
//Program Output:
List1:
206aa77c-8259-428b-a4a0-0e005d8b016c
64f71cc9-596d-4cb8-9eb3-35da3b96f583
List2:
10382452-a7fe-4307-ae4c-41580dc69146
97f3f3f6-6e64-4109-9737-cb72280bc112
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Matches:
64f71cc9-596d-4cb8-9eb3-35da3b96f583
Press any key to continue . . .
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication8
{
class Program
{
static void Main(string[] args)
{
//test initialization
List<ClassTypeA> list1 = new List<ClassTypeA>();
List<ClassTypeB> list2 = new List<ClassTypeB>();
ClassTypeA citem = new ClassTypeA();
ClassTypeB citem2 = new ClassTypeB();
citem2.ID = citem.ID;
list1.Add(new ClassTypeA());
list1.Add(citem);
list2.Add(new ClassTypeB());
list2.Add(new ClassTypeB());
list2.Add(citem2);
//new common list.
List<ICommonTypeMakeUpYourOwnName> common_list =
new List<ICommonTypeMakeUpYourOwnName>();
//in english, give me everything in list 1
//and cast it to the interface
common_list.AddRange(
list1.ConvertAll<ICommonTypeMakeUpYourOwnName>(delegate(
ClassTypeA x) { return (ICommonTypeMakeUpYourOwnName)x; }));
//in english, give me all the items in the
//common list that don't exist in list2 and remove them.
common_list.RemoveAll(delegate(ICommonTypeMakeUpYourOwnName x)
{ return list2.Find(delegate(ClassTypeB y)
{return y.ID == x.ID;}) == null; });
//show list1
Console.WriteLine("List1:");
foreach (ClassTypeA item in list1)
{
Console.WriteLine(item.ID);
}
//show list2
Console.WriteLine("\nList2:");
foreach (ClassTypeB item in list2)
{
Console.WriteLine(item.ID);
}
//show the common items
Console.WriteLine("\nMatches:");
foreach (ICommonTypeMakeUpYourOwnName item in common_list)
{
Console.WriteLine(item.ID);
}
}
}
interface ICommonTypeMakeUpYourOwnName
{
Guid ID { get; set; }
}
class ClassTypeA : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff1;
public int Stuff1 {get { return _Stuff1; } set { _Stuff1 = value;}}
string _Stuff2;
public string Stuff2 {get { return _Stuff2; } set { _Stuff2 = value;}}
public ClassTypeA()
{
this.ID = Guid.NewGuid();
}
}
class ClassTypeB : ICommonTypeMakeUpYourOwnName
{
Guid _ID;
public Guid ID {get { return _ID; } set { _ID = value;}}
int _Stuff3;
public int Stuff3 {get { return _Stuff3; } set { _Stuff3 = value;}}
string _Stuff4;
public string Stuff4 {get { return _Stuff4; } set { _Stuff4 = value;}}
public ClassTypeB()
{
this.ID = Guid.NewGuid();
}
}
}
Using only .NET 2.0 methods:
class Foo
{
public Guid Guid { get; }
}
List<Foo> GetFooSubset(List<Foo> foos, List<Guid> guids)
{
return foos.FindAll(foo => guids.Contains(foo.Guid));
}
If your classes don't implement a common interface, you'll have to implement GetFooSubset for each type individually.
I'm not sure that I fully understand what you want, but you can use linq to select out the matching items from the lists as well as sorting them. Here is a simple example where the values from one list are filtered on another and sorted.
List<int> itemList = new List<int>() { 9,6,3,4,5,2,7,8,1 };
List<int> filterList = new List<int>() { 2, 6, 9 };
IEnumerable<int> filtered = itemList.SelectMany(item => filterList.Where(filter => filter == item)).OrderBy(p => p);
I haven't had a chance to use AutoMapper yet, but from what you describe you wish to check it out. From Jimmy Bogard's post:
AutoMapper conventions
Since AutoMapper flattens, it will
look for:
Matching property names
Nested property names (Product.Name
maps to ProductName, by assuming a
PascalCase naming convention)
Methods starting with the word “Get”,
so GetTotal() maps to Total
Any existing type map already
configured
Basically, if you removed all the
“dots” and “Gets”, AutoMapper will
match property names. Right now,
AutoMapper does not fail on mismatched
types, but for some other reasons.
I am not totally sure what you want as your end results, however....
If you are comparing the properties on two different types you could project the property names and corresponding values into two dictionaries. And with that information do some sort of sorting/difference of the property values.
Guid newGuid = Guid.NewGuid();
var classA = new ClassA{Id = newGuid};
var classB = new ClassB{Id = newGuid};
PropertyInfo[] classAProperties = classA.GetType().GetProperties();
Dictionary<string, object> classAPropertyValue = classAProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classA, null));
PropertyInfo[] classBProperties = classB.GetType().GetProperties();
Dictionary<string, object> classBPropetyValue = classBProperties.ToDictionary(pName => pName.Name,
pValue =>
pValue.GetValue(classB, null));
internal class ClassB
{
public Guid Id { get; set; }
}
internal class ClassA
{
public Guid Id { get; set; }
}
classAPropertyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
classBPropetyValue
Count = 1
[0]: {[Id, d0093d33-a59b-4537-bde9-67db324cf7f6]}
Thist should essentially get you what you want - but you may be better of using linq
class T1
{
public T1(Guid g, string n) { Guid = g; MyName = n; }
public Guid Guid { get; set; }
public string MyName { get; set; }
}
class T2
{
public T2(Guid g, string n) { ID = g; Name = n; }
public Guid ID { get; set; }
public string Name { get; set; }
}
class Test
{
public void Run()
{
Guid G1 = Guid.NewGuid();
Guid G2 = Guid.NewGuid();
Guid G3 = Guid.NewGuid();
List<T1> t1s = new List<T1>() {
new T1(G1, "one"),
new T1(G2, "two"),
new T1(G3, "three")
};
List<Guid> filter = new List<Guid>() { G2, G3};
List<T1> filteredValues1 = t1s.FindAll(delegate(T1 item)
{
return filter.Contains(item.Guid);
});
List<T1> filteredValues2 = t1s.FindAll(o1 => filter.Contains(o1.Guid));
}
}

Categories

Resources