I was originally experiencing a problem in my code in which I was unable to "add" an item to a list object. After reviewing the list object however, I realized it only contained a "get", not a "set". So, I'm trying to create a set accessor but I'm having issues:
Here's my original code to add an item to the list object. Currently, nothing gets added:
ClientCompany clientCompany = new ClientCompany();
LocationData urlData = new LocationData();
Location location = urlData.LocationGet(1129); //hardcoded 1129 in for now
clientCompany.Locations.Add(location); //"location" is NOT null, however nothing gets added to Locations object
return clientCompany; //clientCompany.Locations.Count = 0 (it should equal 1)
And here's the current portion of the ClientCompany class I'm having trouble with:
public Dictionary<int, Location> LocationsDict { get; set; }
// List Properties
public List<Location> Locations
{
get { return LocationsDict.Values.ToList(); }
}
I tried including a setter, but I receive the following error:
Cannot convert source type
Systems.Collections.Generic.List<MyCompany.MVC.MyProject.Models.ClientCompany.Location>'
to target type 'Systems.Collections.Generic.Dictionary<int,
MyCompany.MVC.MyProject.Models.ClientCompany.Location>
get { return LocationsDict.Values.ToList(); }
set { LocationsDict = value; }
Any idea what I'm doing wrong?
Thanks
i 'll do something like this:
private Dictionary<int, Location> LocationsDict = new Dictionary<int, Location>();
public void Set(int key, Location value)
{
if (LocationsDict.ContainsKey(key))
LocationsDict[key] = value;
else
LocationsDict.Add(key, value);
}
public Location Get(int key)
{
return LocationsDict.ContainsKey(key) ? LocationsDict[key] : null; }
}
or better (i think) you could use indexer:
public class MyClass
{
private readonly IDictionary<int, Location> LocationsDict = new Dictionary<int, Location>();
public Location this[int key]
{
get { return LocationsDict.ContainsKey(key) ? LocationsDict[key] : null; }
set
{
if (LocationsDict.ContainsKey(key))
LocationsDict[key] = value;
else
LocationsDict.Add(key, value);
}
}
}
var gotest = new MyClass();
gotest[0] = new Location(){....};
Related
I'm trying to implement a class with a property which can be accessed only with parameter. To clear my question see how I intend to use it
Note that this is different than Indexer. Please don't flag for duplicate.
My incomplete class
public class Inventory{
public object Options..... // I don't know how to define this property
}
How I'm going to use it
Inventory inv = new Inventory();
string invLabel = (string)inv.Options["Label"];
int size = inv.Options["Size"];
inv.Options["Weight"] = 24;
Internally, Options reads data from a private Dictionary. Please help me on how I can define the Options property.
Note: This is different than Indexer. With Indexer, I can use below code:
int size = inv["Size"];
But my usage is different.
I found a way to implement it.
public class Options
{
public Dictionary<string, object> _options;
public Options()
{
_options = new Dictionary<string, object>();
}
public object this[string key] {
get { return _options.Single(r => r.Key == key).Value; }
set { _options[key] = value; }
}
}
public class Inventory
{
public Inventory()
{
Options = new Options();
}
public Options Options { get; set; }
}
Usage:
var x = new Inventory();
x.Options["Size"] = 120;
x.Options["Box"] = "4 x 4 x 8";
Console.WriteLine(x.Options["Size"]);
Console.WriteLine(x.Options["Box"]);
Let us suppose we have a class like below :-
class DoubleLinkedListNode
{
public int Value { get; set; }
public DoubleLinkedListNode(int value)
{
Value = value;
}
public DoubleLinkedListNode next = null;
public DoubleLinkedListNode prev = null;
}
And then we create a dictionary as given below :-
IDictionary<int, DoubleLinkedListNode> dict = new Dictionary<int, DoubleLinkedListNode>();
The key of the dictionary will hold the Value of the DoubleLinkedListNode that it contains like this :-
DoubleLinkedListNode newNode = new DoubleLinkedListNode(value);
dict.Add(newNode.Value, newNode );
Let us also create a function which takes the type of the value of the dictionary as input and we make that value null inside the body of the function as shown below :-
private void RemoveNode(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
//Do Something
nodeToBeRemoved = null;
}
}
and we call the function like this :-
RemoveNode(dict[someValue]);
Let us create another function in which we make the value null explicitly as shown below :-
private void RemoveNodeAnother(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
//Do Something
dict[nodeToBeRemoved.Value] = null;
}
}
And then we call the function like this :-
RemoveNodeAnother(dict[someValue]);
What is the difference between the above two functions ?
Why I am asking is this I was doing this question on Leetcode. The solution that I wrote is as follows :-
public class FirstUnique
{
private class DoubleLinkedListNode
{
public int Value { get; set; }
public DoubleLinkedListNode(int value)
{
Value = value;
}
public DoubleLinkedListNode next = null;
public DoubleLinkedListNode prev = null;
}
DoubleLinkedListNode dummyHeadNode = new DoubleLinkedListNode(-1);
DoubleLinkedListNode dummyTailNode = new DoubleLinkedListNode(-1);
IDictionary<int, DoubleLinkedListNode> dict = new Dictionary<int, DoubleLinkedListNode>();
public FirstUnique(int[] nums)
{
InitialiseDummyHeadAndTailNodes();
foreach(int i in nums)
{
Add(i);
}
}
public int ShowFirstUnique()
{
return dummyHeadNode.next.Value;
}
public void Add(int value)
{
if (dict.ContainsKey(value))
{
RemoveNode(dict[value]);
}
else
{
DoubleLinkedListNode newNode = new DoubleLinkedListNode(value);
AddNode(newNode);
}
}
private void InitialiseDummyHeadAndTailNodes()
{
dummyHeadNode.next = dummyTailNode;
dummyTailNode.prev = dummyHeadNode;
}
private void RemoveNode(DoubleLinkedListNode nodeToBeRemoved)
{
if(nodeToBeRemoved != null)
{
nodeToBeRemoved.prev.next = nodeToBeRemoved.next;
nodeToBeRemoved.next.prev = nodeToBeRemoved.prev;
// If I write nodeToBeRemoved = null, the solution won't pass.
// But if I write dict[nodeToBeRemoved.Value] = null, the solution is accepted.
dict[nodeToBeRemoved.Value] = null;
}
}
private void AddNode(DoubleLinkedListNode nodeToBeAdded)
{
//Update the pointers.
nodeToBeAdded.prev = dummyTailNode.prev;
nodeToBeAdded.prev.next = nodeToBeAdded;
nodeToBeAdded.next = dummyTailNode;
dummyTailNode.prev = nodeToBeAdded;
//Add the node to the dictionary.
dict.Add(nodeToBeAdded.Value, nodeToBeAdded);
}
}
I have made the comments where the anomaly lies. What could be the reason for this behavior ?
There is only one way to "set dictionary value to null" -
dictionary[key] = null;
indeed, if key is not there you need to add it first... Which leads to the way to set value to null -
if (dictionary.ContainsKey(key))
dictionary[key] = null;
else
dictionary.Add(key, null);
Note that setting value to null has zero impact on what was stored there previously.
I have created a class in my ASP.Net project called LitHoldModifications. Here's the code:
[Serializable]
public class LitHoldModifications
{
private Boolean _changed;
private Hashtable _added;
private Hashtable _deleted;
public Boolean Changed
{
get { return _changed; }
set { _changed = value; }
}
public Hashtable Added
{
get { return _added; }
set { _added = value; }
}
public Hashtable Deleted
{
get { return _deleted; }
set { _deleted = value; }
}
public Hashtable Add(String item1, String item2)
{
Added = new Hashtable();
Added.Add(item1, item2);
return Added;
}
public Hashtable Delete(String item1, String item2)
{
Deleted = new Hashtable();
Deleted.Add(item1, item2);
return Deleted;
}
}
The problem I'm having is that I need to be able to Add multiple items to an instance of this class. The code I have to do this is (in an aspx page):
public LitHoldModifications AffectedEmployeeModifications
{
get
{
if (ViewState["AffectedEmployeeModifications"] != null)
return (LitHoldModifications)ViewState["AffectedEmployeeModifications"];
else
return null;
}
set
{
ViewState["AffectedEmployeeModifications"] = value;
}
}
protected void ProcessAffectedviaJavascript()
{
string[] employees = HiddenEmployeesPopup.Value.Split('|');
if (employees.Length>1) {
foreach (string s in employees)
{
if (s.Length > 1)
{
string Anumber = s.Split('#')[0];
string AName = s.Split('#')[1];
ListItem item = new ListItem();
item.Text = AName;
item.Value = Anumber;
lstSelEmployees.Items.Add(item);
//Clear values in temp hidden field:
HiddenEmployeesPopup.Value = "";
AffectedEmployeeModifications.Add(Anumber, AName);
AffectedEmployeeModifications.Changed = true;
}
}
}
When I run my code and get to ProcessAffectedviaJavascript(), the string[] employees is populated with multiple names, but each time the code gets to the line AffectedEmployeeModifications.Add.... a new Hashtable is created and returned by the Add method, so any earlier strings from employees that have been added to AffectedEmployeeModifications are lost. The only way I can think to get around this is to change the Add method to take AffectedEmployeeModifications as a parameter and do this:
public Hashtable Add(Hashtable lhm, String item1, String item2)
{
lhm.Add(item1, item2);
return lhm;
}
and then, in my aspx.cs:
AffectedEmployeeModifications = AffectedEmployeeModifications.Add(AffectedEmployeeModifications, Anumber, AName);
This doesn't seem very OOP-y though, and my OOP skills are clearly wanting. How should I do this?
You should be constructing the objects that your class needs in a constructor for the class. You should add a default constructor like this:
public LitHoldModifications()
{
Added = new Hashtable();
Deleted = new Hashtable();
}
Then you can remove the assignments in your Add() and Delete() methods, because you can assume in these methods that those member variables will already be valid.
I would also recommend changing your Add/Delete methods to returning void. If you want access to the Added/Deleted hashtables, you can just reference that property instead.
var myLitInstance = new LitHoldModifications();
myLitInstance.Add("value1", "value2");
Hashtable tbl = myLitInstance.Added;
I have a (string, object) dictionary, object (class) has some values including data type which is defined by enum. I need a GetItemValue method that should return dictionary item's value. So return type must be the type which is defined in item object.
Class Item
{
String Name;
DataValueType DataType;
Object DataValue;
}
private Dictionary<string, Item> ItemList = new Dictionary<string, Item>();
void Main()
{
int value;
ItemList.Add("IntItem", new Item("IntItem", DataValueType.TInt, 123));
value = GetItemValue("IntItem"); // value = 123
}
What kind of solution can overcome this problem?
Best Regards,
You can use Generic Classes
Class Item<T>
{
String Name;
T DataTypeObject;
Object DataValue;
public T GetItemValue()
{
//Your code
return DataTypeObject;
}
}
A better solution would be to introduce an interface that you make all the classes implement. Note that the interface doesn't necessarily have to specify any behavior:
public interface ICanBePutInTheSpecialDictionary {
}
public class ItemTypeA : ICanBePutInTheSpecialDictionary {
// code for the first type
}
public class ItemTypeB : ICanBePutInTheSpecialDictionary {
// code for the second type
}
// etc for all the types you want to put in the dictionary
To put stuff in the dictionary:
var dict = new Dictionary<string, ICanBePutInTheSpecialDictionary>();
dict.add("typeA", new ItemTypeA());
dict.add("typeB", new ItemTypeB());
When you need to cast the objects to their specific types, you can either use an if-elseif-block, something like
var obj = dict["typeA"];
if (obj is ItemTypeA) {
var a = obj as ItemTypeA;
// Do stuff with an ItemTypeA.
// You probably want to call a separate method for this.
} elseif (obj is ItemTypeB) {
// do stuff with an ItemTypeB
}
or use reflection. Depending on how many choices you have, either might be preferrable.
If you have a 'mixed bag' you could do something like this...
class Item<T>
{
public String Name { get; set; }
public DataValueType DataType { get; set; }
public T DataValue { get; set; }
}
class ItemRepository
{
private Dictionary<string, object> ItemList = new Dictionary<string, object>();
public void Add<T>(Item<T> item) { ItemList[item.Name] = item; }
public T GetItemValue<T>(string key)
{
var item = ItemList[key] as Item<T>;
return item != null ? item.DataValue : default(T);
}
}
and use it like...
var repository = new ItemRepository();
int value;
repository.Add(new Item<int> { Name = "IntItem", DataType = DataValueType.TInt, DataValue = 123 });
value = repository.GetItemValue<int>("IntItem");
If you have just a couple types - you're better off with Repository<T>.
I found a solution exactly what I want. Thanks to uncle Google.
Thanks all of you for your kind interest.
public dynamic GetValue(string name)
{
if (OpcDataList[name].IsChanged)
{
OpcReflectItem tmpItem = OpcDataList[name];
tmpItem.IsChanged = false;
OpcDataList[name] = tmpItem;
}
return Convert.ChangeType(OpcDataList[name].ItemValue.Value, OpcDataList[name].DataType);
}
I'm trying to compare two complex objects in C#, and produce a Dictionary containing the differences between the two.
If I have a class like so:
public class Product
{
public int Id {get; set;}
public bool IsWhatever {get; set;}
public string Something {get; set;}
public int SomeOtherId {get; set;}
}
And one instance, thus:
var p = new Product
{
Id = 1,
IsWhatever = false,
Something = "Pony",
SomeOtherId = 5
};
and another:
var newP = new Product
{
Id = 1,
IsWhatever = true
};
To get the differences between these, i'm doing stuff that includes this:
var oldProps = p.GetType().GetProperties();
var newProps = newP.GetType().GetProperties();
// snip
foreach(var newInfo in newProps)
{
var oldVal = oldInfo.GetValue(oldVersion, null);
var newVal = newInfo.GetValue(newVersion,null);
}
// snip - some ifs & thens & other stuff
and it's this line that's of interest
var newVal = newInfo.GetValue(newVersion,null);
Using the example objects above, this line would give me a default value of 0 for SomeOtherId (same story for bools & DateTimes & whathaveyou).
What i'm looking for is a way to have newProps include only the properties that are explicitly specified in the object, so in the above example, Id and IsWhatever. I've played about with BindingFlags to no avail.
Is this possible? Is there a cleaner/better way to do it, or a tool that's out there to save me the trouble?
Thanks.
There is no flag to tell if you a property was explicitly set. What you could do is declare your properties as nullable types and compare value to null.
If i understand you correctly, this is what microsoft did with the xml wrapping classes, generated with the xsd utility, where you had a XIsSpecified, or something like that, for each property X.
So this is what You can do as well - instead of public int ID{get;set;}, add a private member _id , or whatever you choose to call it, and a boolean property IDSpecified which will be set to true whenever Id's setter is called
I ended up fixing the issue without using reflection (or, not using it in this way at least).
It goes, more or less, like this:
public class Comparable
{
private IDictionary<string, object> _cache;
public Comparable()
{
_cache = new Dictionary<string, object>();
}
public IDictionary<string, object> Cache { get { return _cache; } }
protected void Add(string name, object val)
{
_cache.Add(name, val);
}
}
And the product implementation goes to this:
public class Product : Comparable
{
private int _id;
private bool _isWhatever;
private string _something;
private int _someOtherId;
public int Id {get { return _id; } set{ _id = value; Add("Id", value); } }
public bool IsWhatever { get { return _isWhatever; } set{ _isWhatever = value; Add("IsWhatever ", value); } }
public string Something {get { return _something; } set{ _something = value; Add("Something ", value); } }
public int SomeOtherId {get { return _someOtherId; } set{ _someOtherId = value; Add("SomeOtherId", value); } }
}
And the comparison is then pretty straightforward
var dic = new Dictionary<string, object>();
foreach(var obj in version1.Cache)
{
foreach(var newObj in version2.Cache)
{
//snip -- do stuff to check equality
dic.Add(....);
}
}
Doesn't hugely dirty the model, and works nicely.