C# Single vs List of Objects for a class - c#

I have a class that inherits from an interface and implements a method that saves a single object and another method that saves a list of objects of type lets say 'iX':-
public class XX : iX
{
public override string A;
public override string B;
internal Some_Method(iX item)
{
A = item.A; B - item.B;
}
private void Single_Save(specific_type x)
{
//// some code here ///
}
private void Multiple_Save(List<specific_type> x)
{
/// some code here ///
}
internal void Save()
{
var y = AnotherFunction(this);
Save(y);
}
internal void SaveAll()
{
Multiple_Save(that_list); <----------- how do I get that list ??
}
}
Now from my Business class I would like to do something like this:-
public static void SaveObj(iX item)
{
var singleobj = new XX(item);
singleobj.Save();
}
The single save works. But I am having issues writing code that will allow me to save a list of objects as such:-
public static void SaveObjects(List<iX> items)
{
var multipleobj = new XX(items); <------- this will not work, because my class is expecting a single object of type iX....
multipleobj.SaveAll();
}
** The caveat to this is that, both Multiple_Save and Single_Save methods use different forms of saving info and need to be used separately by respective methods aka cannot foreach through a list of items and Single_Save one at a time.
Can someone point me to the concept I should be looking at to figure this scenario out?

I am not sure what are you trying to do. I can not see the construction of XX class but create a overload constructor
public XX(List<yourClass> item)
{
}
This will have your object.

You need multiple constructors in your class. Provided they have different parameters, method overloading allows you to create multiple methods with the same name.
Example:
public class XX : IX
{
public IX SingleItem { get; set; }
public List<IX> ListOfItems { get; set; }
public XX(IX item)
{
SingleItem = item;
}
public XX(List<IX> items)
{
ListOfItems = items;
}
}
You could even then combine your save methods into one if you wanted too:
public void Save()
{
if (ListOfItems != null)
{
//code to save multiple
}
else if (Item != null)
{
//code to save one
}
}

It would be far simpler if you had a separate a collection class. Let an XX represent a single item, and put them together in a collection if you want to work with them as a unit. It's easy to create a collection class (just inherit from List<T> and all its methods and its enumerator become available from this). For example:
class XXList : List<XX>
{
public void SaveAll()
{
foreach (var xx in this) xx.Save();
}
}
So you can use it like this:
var list = new XXList
{
new XX(item1),
new XX(item2),
new XX(item3)
};
list.SaveAll();

You can use like below:
// Create the list
List<ClassName> List = new List<Ix>();
// Create instance of your class
Ix ix = new Ix();
// Add the new object to the list
classList.Add(ix);
You can also use Types.
In your
private void Multiple_Save(List<specific_type> x)
{
If (x != null)
{
foreach (var ix in x)
SingleSave(ix);
/// some code here ///
}
}
I believe this requires System.Collections.Generic as namespace.

Related

Explicit interface implementation not working when passing into method with higher interface type

I have a class that contains a list of items (implement IHasItems). In a specific scenario, I want to hide these items by explicit implement IHiddenItems to return empty list.
But there is an existing method (PrintItems - in this case), the input parameter type is IHasItems. Consequently, the items can not be hidden in the method even if I cast the object to IHiddenItems.
The reason to try this approach is that I don't want to create a prototype of this object and set it empty in the prototype instance.
public interface IHasItems
{
IEnumerable<string> Items { get; }
}
public interface IHiddenItems : IHasItems
{
new IEnumerable<string> Items { get; }
}
public class Implementation : IHasItems, IHiddenItems
{
public Implementation()
{
Items = new List<string>()
{
"A","B","C"
};
}
public IEnumerable<string> Items { get; }
IEnumerable<string> IHiddenItems.Items { get; } = new List<string>(); // Empty
}
static class Program
{
static void Main()
{
Implementation derivedClass = new Implementation();
Console.WriteLine($"Implementation: {derivedClass.Items.Count()}");
Console.WriteLine($"IHasList: {((IHasItems)derivedClass).Items.Count()}");
Console.WriteLine($"IEmptyList: {((IHiddenItems)derivedClass).Items.Count()}");
PrintItems(((IHiddenItems)derivedClass));
Console.Read();
}
public static void PrintItems(IHasItems obj)
{
Console.WriteLine($"PrintItems method: {obj.Items.Count()}");
}
}
Result
Implementation: 3
IHasList: 3
IEmptyList: 0
PrintItems method: 3
Expected
Without modify PrintItems, it should display to console PrintItems method: 0

Return Different Types Within One Function C#

I am creating a project data pipeline and I need to return different types from a single class
in this class I have a number of Dictionaries that hold and separate the elements/content i want to load up but i need a way to return them with a single string... as i am not to familiar with these Type functions i am lost as to how to return the content properly
I need this in a separate class so i can do a XML serialization later
Here is what I have now
DataClass contents;
public T ReturnType<T>(string asset)
{
if(typeof(T) == typeof(int))
{
return contents.Integers[Asset];
}
if(typeof(T) == typeof(float))
{
return contents.Floats[Asset];
}
if(typeof(T) == typeof(double))
{
return contents.Doubles[Asset];
}
return default(T);
}
it will allow me to use a base Object class to parse the content but i dont want anything to get lost in transit so i am weary in using this method
my question is how to return one of the different objects of a certain types within the class that i am using for serialization with a function like that
If i wanted to use the previous function to grab content within the class eg
public Object someobject;
//button event handler to change the current object
//preferably this would be changed depending on the object i would be calling
//but this should do for showing how it is supposed to work
public void ChangeCurrentObject(event e)
{
someobject = (Object)ReturnType<Object>("23rdObject");
}
it sends a string to the function called 'ReturnType' and returns an object ie(int, float,etc) within there own respective dictionary
The generics in this case will only help you not to write diferent method for every asset type. You can also use this aproach to make it more modular.
static class Assets
{
public interface IAssetHandler<out T>
{
T GetAsset(string name);
}
private static readonly Dictionary<Type,object> _handlers=new Dictionary<Type, object>();
public static T GetAsset<T>(string name)
{
object assetHandler;
if(!_handlers.TryGetValue(typeof(T),out assetHandler))
{
throw new Exception("No handler for that type of asset");
}
return (assetHandler as IAssetHandler<T>).GetAsset(name);
}
public static void RegisterAssetHandler<T>(IAssetHandler<T> handler)
{
_handlers[typeof (T)] = handler;
}
}
public class IntAssetsHandler:Assets.IAssetHandler<int>
{
#region Implementation of IAssetHandler<out int>
public int GetAsset(string name)
{
return 0;
}
#endregion
}
static void Main(string[] args)
{
Assets.RegisterAssetHandler(new IntAssetsHandler());
Console.WriteLine(Assets.GetAsset<int>("test"));
}
You could use external class, set the properties types as you wish, then use it in your function.
public class MultipleOpjects
{
public List<string> ObjectOne { get; set; }
public List<object> ObjectTwo { get; set; }
public object ObjectThree { get; set; }
}
public MultipleOpjects GetAnything()
{
MultipleOpjects Vrble = new MultipleOpjects();
Vrble.ObjectOne = SomeThing1;
Vrble.ObjectTwo = SomeThing2;
Vrble.ObjectThree = SomeThing3;
return Vrble;
}

Generic Class to create a Generic Collection using IEnumerable<T>

This is a Two (2) Part Question about Generics
I've got to create several similar classes to model similarly designed database tables.
All tables contain an ID int and a Text nvarchar(50) field. One or two may contain a few other fields.
I rarely use generics, but I see examples of it on here quite frequently. This is my largest attempt to create a generic class that is used in another generic class.
My basic construct is as follows, and I will point out with a comment what does not work and the error message Visual Studio 2010 is displaying:
public class IdText {
public IdText(int id, string text) {
ID = id;
Text = text;
}
public int ID { get; private set; }
public string Text { get; private set; }
}
public class TCollection<T> : IEnumerable<T> where T : IdText {
private List<T> list;
public TCollection() {
list = new List<T>();
}
public void Add(int id, string text) {
foreach (var item in list) {
if (item.ID == id) {
return;
}
}
list.Add(new T(id, text)); // STOP HERE
// Cannot create an instance of the variable type 'T'
// because it does not have the new() constraint
}
public T this[int index] {
get {
if ((-1 < 0) && (index < list.Count)) {
return list[index];
}
return null;
}
}
public T Pull(int id) {
foreach (var item in list) {
if (item.ID == id) {
return item;
}
}
return null;
}
public T Pull(string status) {
foreach (var item in list) {
if (item.Text == status) {
return item;
}
}
return null;
}
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator() {
foreach (var item in list) yield return item;
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return list.GetEnumerator();
}
#endregion
}
Visual Studio's IntelliSence wants me to add list.Add(T item), but I need to create this first.
I have attempted to re-write the offending line list.Add(new T(id, text)); as list.Add(new IdText(id, text));, but then I am reprimanded with the message "cannot convert from IdText to T".
How exactly do I get around this?
Next: When I go in to actually create a version of this IdText class later, I am not sure how exactly I can use this new class in the TCollection class I have designed for it.
For example, given this derived class:
public class ManufacturedPart : IdText {
public ManufacturedPart(int id, string partNum, string description)
: base(int id, string partNum) {
Description = description;
}
public string Description { get; private set; }
}
...would I need to also derive a special version of TCollection to accompany it, like so?
public class ManufacturedParts<T> : IEnumerable<T> where T : ManufacturedPart {
// OK, now I'm lost! Surely this can't be right!
}
1) You could use the new() constraint, make your properties public and add a parameterless constructor:
public class IdText
{
public IdText()
{
}
public IdText(int id, string text)
{
ID = id;
Text = text;
}
public int ID { get; set; }
public string Text { get; set; }
}
public class TCollection<T> : IEnumerable<T> where T : IdText, new()
{
private List<T> list;
public TCollection()
{
list = new List<T>();
}
public void Add(int id, string text)
{
foreach (var item in list)
{
if (item.ID == id)
{
return;
}
}
list.Add(new T { ID = id, Text = text });
}
}
2) You have multiple options:
If you want your collection to store any IdText (ManufacturedPart or anything else that derived from IdText):
TCollection<IdText> ss = new TCollection<IdText>();
The above, for now, can only store IdText as you instantiate objects in the Add(int, string) method, but if you provide a Add(T object) method, it could store any IdText instance.
If you want your collection to only contains ManufacturedParts:
public class ManufacturedParts<T> : TCollection<T> where T : ManufacturedPart, new()
{
// Provide here some specific implementation related to ManufacturedParts
// if you want. For example, a TotalPrice property if ManufacturedPart
// has a Price property.
}
TCollection<ManufacturedPart> ss2 = new ManufacturedParts<ManufacturedPart>();
or even simpler, if your collection doesn't provide any additional method depending on the type of the stored objects:
TCollection<ManufacturedPart> ss2 = new TCollection<ManufacturedPart>();
Even simpler, if your goal is to only store objects, a custom collection isn't needed:
List<IdText> ss2 = new List<IdText>(); // Uses the built-in generic List<T> type
About the first question: c# doesn't support constructors with parameters as a generic constrain. Something you can do is replace it with
(T)Activator.CreateInstance(typeof(T),new object[]{id,text});
By the other hand... you don't actually know how the constructors of the derived class will look like, so you can't ensure they will have that constructor.
About the second question, you can do this:
var collection = new TCollection<ManufacturedPart>();
in the same way List works.
Hope it helps.
If your collection class will be responsible for instantiating elements of its collected type, then you probably don't want to be using either the new() constraint or Activator.CreateInstance() -- as Jon Skeet has blogged, both of these exhibit poor performance.
It sounds like what you actually want is a provider delegate, like so:
public class MyCollection<T> : IEnumerable<T> where T : IdText {
private readonly List<T> list;
private readonly Func<int, string, T> provider;
public MyCollection(Func<int, string, T> provider) {
this.list = new List<T>();
this.provider = provider;
}
public void Add(int id, string text) {
list.Add(provider(id, text));
}
}
And then you'd use it like:
var collection = new MyCollection((id, text) => new ManufacturedPart(id, text));
You can think of this as passing the specific constructor you want to use as an argument into the class, which it then uses to construct instances as needed.
And you don't need to create a separate subclass for MyCollection<ManufacturedPart> -- just use the generic class directly.

Delegates as Properties: Bad Idea?

Consider the following control (snipped for brevity):
public partial class ConfigurationManagerControl : UserControl
{
public Func<string, bool> CanEdit { get; set;}
public Func<string, bool> CanDelete { get; set; }
public Dictionary<string, string> Settings
{
get { return InnerSettings; }
set
{
InnerSettings = value;
BindData();
}
}
private Dictionary<string, string> InnerSettings;
private void OnListIndexChanged(object sender, EventArgs e)
{
this.EditButton.Enabled = false;
this.DeleteButton.Enabled = false;
var indices = this.List.SelectedIndices;
if (indices.Count != 1)
{
return;
}
var index = indices[0];
var item = this.List.Items[index];
if (this.CanEdit != null)
{
this.EditButton.Enabled = this.CanEdit(item.Text);
}
if (this.CanDelete != null)
{
this.DeleteButton.Enabled = this.CanDelete(item.Text);
}
}
}
There's more to this control, but suffice it to say that it allows a user to add, edit, and delete the entries in a Dictionary<string, string>. In order to determine whether or not it should allow the user to edit or delete the entries, it uses the delegate method properties, CanDelete and CanEdit, which are provided by the form or control that hosts it:
public class SetupWizard : Form
{
public SetupWizard()
{
InitializeComponent();
this.SettingManager.CanEdit = CanEditSetting;
this.SettingManager.CanDelete = CanDeleteSetting;
}
private static bool CanEditSetting(string item)
{
var lockedSettings = new[] { "LicenseHash", "ProductHash" };
return !lockedSettings.Contains(item.ToLower());
}
private static bool CanDeleteSetting(string item)
{
var lockedSettings = new[] {
"LicenseHash",
"ProductHash",
"UserName",
"CompanyName"
};
return !lockedSettings.Contains(item.ToLower());
}
}
I find that this design is both satisfactory and worrisome at the same time. On the one hand, it seems to solve the problem using the simplest solution that works (it certainly separates the concerns nicely). On the other hand, I have this nagging concern that I am using delegates improperly and should be using an event, instead (even though I do not need multiple listeners, and only need the caller to tell me if the item is editable).
And then, on the other other hand, there's the chance that there's a completely different design that I haven't even considered that might solve the problem in a vastly superior way.
So. Is this design technically correct, maintainable, and flexible? Or should I be doing something better?
I suggest the use of an interface with these two methods. That's a lot cleaner:
interface ICantThinkOfAGoodName
{
bool CanEdit(string item);
bool CanDelete(string item);
}
You could create something similar to the RelayCommand used in many MVVM frameworks:
public class RelayObject : ICantThinkOfAGoodName
{
public RelayObject() : this(null, null) {}
public RelayObject(Func<string, bool> canEdit, Func<string, bool> canDelete)
{
if(canEdit == null) canEdit = s => true;
if(canDelete == null) canDelete = s => true;
_canEdit = canEdit;
_canDelete = canDelete;
}
public bool CanEdit(string item)
{
return _canEdit(item);
}
public bool CanDelete(string item)
{
return _canDelete(item);
}
}
Use it like this:
public SetupWizard()
{
InitializeComponent();
this.SettingManager.PropertyName = new RelayObject(CanEditSetting,
CanDeleteSetting);
// or (all can be deleted)
this.SettingManager.PropertyName = new RelayObject(CanEditSetting, null);
// or (all can be edited)
this.SettingManager.PropertyName = new RelayObject(null, CanDeleteSetting);
// or (all can be edited and deleted)
this.SettingManager.PropertyName = new RelayObject();
}
BTW: I am using Property injection here, because it is a control. Normally, I would pass the ICantThinkOfAGoodName dependency in the constructor of the ConfigurationManagerControl.
It may be this is what #Daniel Hilgarth is suggesting when he says "use an interface" (n.b. - his answer now reflects a more general/flexible approach to implementing the interface). Instead of assigning delegates to your method directly, why not give the control a property, such as DataState or whatever you want to call it, using an interface that encapsulates the information you need, and leave it up to the owner to decide how to implement that.
interface IDataState
{
bool CanEdit(string item);
bool CanDelete(string item);
}
public partial class ConfigurationManagerControl : UserControl
{
public IDataState DataState {get;set;}
// your code checks DataState.CanEdit & DataState.CanDelete
}
public class SetupWizard : Form, IDataState
{
public SetupWizard()
{
InitializeComponent();
SettingManager.DataState =this;
}
public bool CanEdit(string item)
{
... implement directly or return from your private function
}
public bool CanDelete(string item)
{
}
}
But this gives you the flexibility to implement that interface any way you choose, with another object, etc. and it makes it easy to also just pass the owner itself (implementing the interface).

Controlling access to an internal collection in c# - Pattern required

This is kind of hard to explain, I hope my English is sufficient:
I have a class "A" which should maintain a list of objects of class "B" (like a private List). A consumer of class "A" should be able to add items to the list. After the items are added to the list, the consumer should not be able to modify them again, left alone that he should not be able to temper with the list itself (add or remove items). But he should be able to enumerate the items in the list and get their values. Is there a pattern for it? How would you do that?
If the question is not clear enough, please let me know.
To prevent editing the list or its items you have to make them immutable, which means you have to return a new instance of an element on every request.
See Eric Lippert's excellent series of "Immutability in C#": http://blogs.msdn.com/ericlippert/archive/tags/Immutability/C_2300_/default.aspx (you have to scroll down a bit)
As many of these answers show, there are many ways to make the collection itself immutable.
It takes more effort to keep the members of the collection immutable. One possibility is to use a facade/proxy (sorry for the lack of brevity):
class B
{
public B(int data)
{
this.data = data;
}
public int data
{
get { return privateData; }
set { privateData = value; }
}
private int privateData;
}
class ProxyB
{
public ProxyB(B b)
{
actual = b;
}
public int data
{
get { return actual.data; }
}
private B actual;
}
class A : IEnumerable<ProxyB>
{
private List<B> bList = new List<B>();
class ProxyEnumerator : IEnumerator<ProxyB>
{
private IEnumerator<B> b_enum;
public ProxyEnumerator(IEnumerator<B> benum)
{
b_enum = benum;
}
public bool MoveNext()
{
return b_enum.MoveNext();
}
public ProxyB Current
{
get { return new ProxyB(b_enum.Current); }
}
Object IEnumerator.Current
{
get { return this.Current; }
}
public void Reset()
{
b_enum.Reset();
}
public void Dispose()
{
b_enum.Dispose();
}
}
public void AddB(B b) { bList.Add(b); }
public IEnumerator<ProxyB> GetEnumerator()
{
return new ProxyEnumerator(bList.GetEnumerator());
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
}
The downside of this solution is that the caller will be iterating over a collection of ProxyB objects, rather than the B objects they added.
EDIT: Added support for edition contexts. Caller can only add elements inside an edition context. You can aditionally enforce that only one edition context can be created for the lifetime of the instance.
Using encapsulation you can define any set of policies to access the inner private member. The following example is a basic implementation of your requirements:
namespace ConsoleApplication2
{
using System;
using System.Collections.Generic;
using System.Collections;
class B
{
}
interface IEditable
{
void StartEdit();
void StopEdit();
}
class EditContext<T> : IDisposable where T : IEditable
{
private T parent;
public EditContext(T parent)
{
parent.StartEdit();
this.parent = parent;
}
public void Dispose()
{
this.parent.StopEdit();
}
}
class A : IEnumerable<B>, IEditable
{
private List<B> _myList = new List<B>();
private bool editable;
public void Add(B o)
{
if (!editable)
{
throw new NotSupportedException();
}
_myList.Add(o);
}
public EditContext<A> ForEdition()
{
return new EditContext<A>(this);
}
public IEnumerator<B> GetEnumerator()
{
return _myList.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}
public void StartEdit()
{
this.editable = true;
}
public void StopEdit()
{
this.editable = false;
}
}
class Program
{
static void Main(string[] args)
{
A a = new A();
using (EditContext<A> edit = a.ForEdition())
{
a.Add(new B());
a.Add(new B());
}
foreach (B o in a)
{
Console.WriteLine(o.GetType().ToString());
}
a.Add(new B());
Console.ReadLine();
}
}
}
You basically want to avoid to give away references to the class B items. That's why you should do a copy of the items.
I think this can be solved with the ToArray() method of a List object. You need to create a deep-copy of the list if you want to prevent changes.
Generally speaking: most of the times it is not worthwhile to do a copy to enforce good behaviour, especially when you also write the consumer.
public class MyList<T> : IEnumerable<T>{
public MyList(IEnumerable<T> source){
data.AddRange(source);
}
public IEnumerator<T> GetEnumerator(){
return data.Enumerator();
}
private List<T> data = new List<T>();
}
The downside is that a consumer can modify the items it gets from the Enumerator, a solution is to make deepcopy of the private List<T>.
It wasn't clear whether you also needed the B instances themselves to be immutable once added to the list. You can play a trick here by using a read-only interface for B, and only exposing these through the list.
internal class B : IB
{
private string someData;
public string SomeData
{
get { return someData; }
set { someData = value; }
}
}
public interface IB
{
string SomeData { get; }
}
The simplest that I can think of is return a readonly version of the underlying collection if editing is no longer allowed.
public IList ListOfB
{
get
{
if (_readOnlyMode)
return listOfB.AsReadOnly(); // also use ArrayList.ReadOnly(listOfB);
else
return listOfB;
}
}
Personally though, I would not expose the underlying list to the client and just provide methods for adding, removing, and enumerating the B instances.
Wow, there are some overly complex answers here for a simple problem.
Have a private List<T>
Have an public void AddItem(T item) method - whenever you decide to make that stop working, make it stop working. You could throw an exception or you could just make it fail silently. Depends on what you got going on over there.
Have a public T[] GetItems() method that does return _theList.ToArray()

Categories