How to comply DRY principle if two functions are almost the same? - c#

I have two functions which are almost the same. Is there a good way to remove duplicates?
I think about moving duplicated code in the separate function and pass a function as the argument.
private object GetValue(object key)
{
var index = GetHash(key);
var node = _table[index];
while (node != null)
{
if (Equals(node.Key, key)) return node.Value;
node = node.Next;
}
throw new KeyNotFoundException("Such key doesn't exist");
}
private void SetValue(object key, object value)
{
var index = GetHash(key);
var node = _table[index];
if(value == null) RemoveValue(key);
while (node != null)
{
if (Equals(node.Key, key))
{
node.Value = value;
return;
}
node = node.Next;
}
throw new KeyNotFoundException("Such key doesn't exist");
}

Sure, seems reasonable.
private Node GetNode(object key)
{
var index = GetHash(key);
var node = _table[index];
while (true)
{
if (node == null)
throw ...
if (Equals(node.Key, key))
return node;
node = node.Next;
}
}
private object GetValue(object key) => GetNode(key).Value;
private void SetValue(object key, object value)
{
if (value == null)
RemoveValue(key);
else
GetNode(key).Value = value;
}
Now, always ask yourself "how can I improve this further?" Some thoughts:
Why are these methods private? Are they implementation details of a nice public API, with a proper indexer?
Object, in 2018? Use generics!
And so on.

Split each of your methods in two parts:
Finding the target node (private helper), and
Doing something to the target node if it exists
Finding the target node should have this signature:
private Node FindNodeByKey(object key) {
...
}
This method would be in charge of throwing KeyNotFoundException, so both getter and setter could assume that when FindNodeByKey returns a value, it is not null. This assumption lets you reduce the getter to a single line:
private object GetValue(object key) {
return FindNodeByKey(key).Value;
}
private void SetValue(object key, object value) {
if (value == null) {
RemoveValue(key);
} else {
FindNodeByKey(key).Value = value;
}
}

Related

Mixed-Type Generic C# Stack (Linked List Implementation)

I realize that in most cases, it would be beneficial to have a homogeneous, type-safe stack, but I'm curious if this is possible, as I was asked to create a Stack for an exercise which accepts all types.
So I currently have a generic linked-list Stack class, and I'm wondering if there's any way to make the Node class generic so that the Next node can be of a different type. I know I can make the stack accept all types by just making the all the type parameters object instead of using a generic, but I was warned of the performance implications of boxing & unboxing of value types / upcasting all of it's elements to the base object class.
So I went ahead an implemented it as Generic, but was unable to find a solution that allowed different types for each Node. If I wanted to avoid the object approach, is there a possible solution? Even if it takes a different approach altogether, it doesn't necessarily have to fit this approach.
I hope this makes sense! At any rate, here's the implementation I currently have. Please let me know what you think.
Node.cs
namespace DataStructures
{
class Node<T>
{
public T Value { get; private set; }
public Node<T> Next { get; set; }
public Node(T value)
{
Value = value;
}
}
}
Stack.cs
namespace DataStructures
{
class Stack<T>
{
private Node<T> root;
public int Size { get; private set; } = 0;
public Stack()
{
}
public Stack(params T[] values)
{
foreach (var value in values)
Push(value);
}
public void Push(T value)
{
if (value == null)
throw new ArgumentNullException("value", "You cannot push a null value onto the stack");
var newNode = new Node<T>(value);
if (root != null)
newNode.Next = root;
root = newNode;
Size++;
}
public dynamic Peek()
{
if (root == null)
return null;
return root.Value;
}
public T Pop()
{
if (root == null)
throw new InvalidOperationException("The stack is empty, nothing to pop");
Size--;
var popped = root.Value;
root = root.Next;
return popped;
}
public bool TryPop(out dynamic popped)
{
if (root == null)
{
popped = null;
return false;
}
else
{
popped = Pop();
return true;
}
}
public bool IsEmpty() => root == null ? true : false;
public void Clear()
{
root = null;
}
}
}

Map two objects using reflection c#

I'm creating a function to loop over an object and its childs.
But I'm having some issue when i try to map from the original object to the new object, here is the code:
public static bool MatchObjectField<T>(this T obj, string objectRoute, string value)
{
try
{
var objectroutelist = objectRoute.Split('.');
var objroute = objectroutelist.First();
var childproperty = typeof(T).GetProperty(objroute);
if (objectroutelist.Count() == 1)
{
if (childproperty.GetValue(obj).ToString().Trim() == value)
{
return true;
}
return false;
}
else
{
var instance = Activator.CreateInstance(childproperty.PropertyType);
//childproperty.SetValue(obj, instance, null);
//childproperty.SetValue(instance, obj, null);
instance.MapValues(childproperty);
instance.MatchObjectField(string.Join(".", objectroutelist.Skip(1)), value);
}
}
catch (Exception e)
{
return false;
}
return false;
}
And here the class where I do the map and contains the issue.
public static void MapValues<T>(this T destination, PropertyInfo orgproperty)
{
var orgvalues = orgproperty.GetPropertiesWithValues();
var instance = Activator.CreateInstance(typeof(T));
foreach (var property in (typeof(T)).GetProperties())
{
try
{
var value = orgvalues.FirstOrDefault(a => a.Key == property.Name);
property.SetValue(instance, value);
}
catch (Exception)
{
property.SetValue(instance, null);
}
}
destination = (T)(object)instance;
}
The idea of the function is call with objectName.MatchObjectField("parent.child.child.child","MyName")
When I try to compare a field in the parent like objectName.MatchObjectField("Country","Ireland") it works perfectly
But when I try to create the child structure doing a call like objectName.MatchObjectField("Country.Address.City","Dublin") it breaks when I try to map to the new object.
What I noticed is that the property destination into the method MapValues<T> is mapped as Country.Address with all the properties as null which is correct.
But (typeof(T)).GetProperties() doesn't return anything.
Also i noticed that Activator.CreateInstance(typeof(T)) retunrs type {object} instead of return Country.Address
that may be the reason why is not working.
Any idea how to fix this?
EDIT: add get properties with values-> it retuns a Dictionary<string, object>
public static Dictionary<string, object> GetPropertiesWithValues(this Object obj, bool includeValueTypes = true)
{
return InternalGetProperties(obj, false, includeValueTypes);
}
private static Dictionary<string, object> InternalGetProperties(Object obj, bool withDefaultValue, bool includeValueTypes = true)
{
Dictionary<string, object> d = new Dictionary<string, object>();
var res = GetPropertiesR(obj, d, "", withDefaultValue, includeValueTypes);
return res;
}
private static Dictionary<string, object> GetPropertiesR(Object obj, Dictionary<string, object> d, string parent, bool searchingForDefaults, bool includeValueTypes)
{
if (obj == null)
return d;
var pis = #obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
if (pis == null || pis.Length == 0)
throw new InvalidOperationException("This object doens't have inner properties");
Func<string, string> formatProperty = (property) => string.Concat(parent, parent == "" ? "" : ".", property);
foreach (var pi in pis)
{
object data = pi.GetValue(#obj, null);
// check if is value type
if (pi.PropertyType.IsValueType)
{
// data is never null
if (!includeValueTypes)
continue;
Type nullableType = Nullable.GetUnderlyingType(pi.PropertyType);
object defaultValue = nullableType != null ? GetDefault(nullableType) : GetDefault(data.GetType());
if (!searchingForDefaults)
{
// check default values.
if (data != null && data.ToString() != defaultValue.ToString())
d.Add(formatProperty(pi.Name), data);
}
else
{
// check default values
if ((nullableType != null && data == null) || data.ToString() == defaultValue.ToString())
d.Add(formatProperty(pi.Name), data);
}
}
else
{
//
// reference types
if (!searchingForDefaults)
{
if (data == default(object))
continue;
if (IsThisPropertyPartofSystemNamespace(pi))
{
// transform list into a string with values.
IEnumerable enumeration = data as IList;
if (enumeration != null)
{
StringBuilder sb = new StringBuilder();
foreach (var i in enumeration)
sb.Append(string.Concat(i.ToString(), ", "));
if (sb.Length >= 2)
sb.Remove(sb.Length - 2, 2);
data = sb.ToString();
}
d.Add(formatProperty(pi.Name), data);
}
else
{
//
// user complex type defined
string ctxParent = string.Concat(parent, parent == "" ? "" : ".", pi.Name);
GetPropertiesR(data, d, ctxParent, searchingForDefaults, includeValueTypes);
}
}
else
{
if (data != default(object))
continue;
d.Add(formatProperty(pi.Name), data);
}
}
}
return d;
}
private static bool IsThisPropertyPartofSystemNamespace(PropertyInfo pi)
{
var systemNames = new HashSet<string>
{
"mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken={TOKENKEY}",
"System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken={TOKENKEY}"
};
var isSystemType = systemNames.Contains(pi.PropertyType.Assembly.FullName);
return isSystemType;
}
private static object GetDefault(Type type)
{
if (type.IsValueType)
{
return Activator.CreateInstance(type);
}
return null;
}
TL;DR: Take a step back. Describe the responsibility of each of the methods separately, and write tests for them that way. Start with the "lowest level" method and work your way up. That will make it a lot easier to see what's going wrong.
There are multiple problems here. First look at these two lines of code:
var instance = Activator.CreateInstance(childproperty.PropertyType);
instance.MapValues(childproperty);
The return type of Activator.CreateInstance is object, so this is effectively:
var instance = Activator.CreateInstance(childproperty.PropertyType);
instance.MapValues<object>(childproperty);
That's not what you want - you want to use childproperty.PropertyType as the type argument to MapValues. You don't know that at compile-time, so it's not a good fit as a type parameter.
But beyond that, your MapValues method has a bigger problem: it basically ignores its parameter. The only time it uses destination is in the last line, when it assigns a new value to it:
destination = (T)(object)instance;
That parameter is a value parameter, so assigning it at the end of the method is pointless.
You should decide what the purpose of MapValues is:
Is it to create an instance and populate it, then return it?
Is it to accept an existing instance and populate that?
Either is simple enough to implement, but at the moment you're half way between the two. Also note that you're only passing in a single PropertyInfo - consider how you'd expect to assign multiple properties with that.
Finally, there's the matter of where the values come from. You're currently calling GetPropertiesWithValues on the PropertyInfo - that's not going to do what I think you expect it to. You need to provide the source object itself, otherwise there's nowhere to get values from.
I found what i need to do in this post: Getting Nested Object Property Value Using Reflection
getting the nested object is an easy way of what i was pretending to do.
public static object GetPropertyValue(object src, string propName)
{
if (src == null) throw new ArgumentException("Value cannot be null.", "src");
if (propName == null) throw new ArgumentException("Value cannot be null.", "propName");
if(propName.Contains("."))//complex type nested
{
var temp = propName.Split(new char[] { '.' }, 2);
return GetPropertyValue(GetPropertyValue(src, temp[0]), temp[1]);
}
else
{
var prop = src.GetType().GetProperty(propName);
return prop != null ? prop.GetValue(src, null) : null;
}
}
public static bool MatchObjectField<T>(this T obj, string objectRoute, string value)
{
try
{
var propvalue = GetPropertyValue(obj, objectRoute);
return ( propvalue.ToString().Trim() == value.Trim());
}
catch (Exception) {
throw;
}
}

Binary search tree remove with reference to parents

First off, this is a school assignment, so there. I wouldn't be posting if it weren't for the fact that I'm really hurting for help.
Now we have this binary search tree we are supposed to implement. Basically, this class below is complete, I am given to understand.
public class BinarySearchTree<T> where T : IComparable<T>
{
BinarySearchTreeNode<T> _root;
public BinarySearchTreeNode<T> Root
{
get { return _root; }
}
public BinarySearchTree()
{
}
public BinarySearchTree(BinarySearchTreeNode<T> root)
{
_root = root;
}
public void Insert(T value)
{
if (_root != null)
_root.Insert(value);
else
_root = new BinarySearchTreeNode<T>(value);
}
public void Remove(T value)
{
if (_root == null)
return;
if (_root.LeftChild != null || _root.RightChild != null)
{
_root.Remove(value);
}
else if (_root.Value.CompareTo(value) == 0)
{
_root = null;
}
}
public bool Find(T value)
{
if (_root != null)
return _root.Find(value);
else
return false;
}
}
And here the class I am supposed to implement, or at least as far as I have gotten.
public class BinarySearchTreeNode<T> where T : IComparable<T>
{
private T _value;
public T Value
{
get { return _value; }
}
public BinarySearchTreeNode<T> LeftChild
{
get { return _leftChild; }
set { _leftChild = value; }
}
private BinarySearchTreeNode<T> _leftChild, _parent, _rightChild;
public BinarySearchTreeNode<T> RightChild
{
get { return _rightChild; }
set { _rightChild = value; }
}
public BinarySearchTreeNode<T> Parent
{
get { return _parent; }
set { _parent = value; }
}
public BinarySearchTreeNode(T value)
{
_value = value;
Parent = this;
}
public void Insert(T value)
{
if (value.CompareTo(Parent.Value) < 0)
{
if (LeftChild != null)
{
LeftChild.Insert(value);
}
else
{
LeftChild = new BinarySearchTreeNode<T>(value);
LeftChild.Parent = this;
}
}
else if (Value.CompareTo(Parent.Value) >= 0)
{
if (RightChild != null)
RightChild.Insert(value);
else{
RightChild = new BinarySearchTreeNode<T>(value);
Righthild.Parent = this;
}
}
}
public void Remove(T value)
{
if (LeftChild != null)
if (value.CompareTo(Parent.Value) < 0)
LeftChild.Remove(value);
else if (RightChild != null)
if (value.CompareTo(Parent.Value) >= 0)
RightChild.Remove(value);
}
public bool Find(T value)
{
if (value.Equals(Parent.Value))
return true;
else if (value.CompareTo(Parent.Value) < 0)
{
if (LeftChild != null)
return LeftChild.Find(value);
}
else if (value.CompareTo(Parent.Value) > 0)
{
if (RightChild != null)
return RightChild.Find(value);
}
return false;
}
}
The issue is that I can't quite seem to get my head around just how I am supposed to properly implement remove, so that I can remove a node simply by pointing towards the parents, for instance. Any help or hints is appreciated.
Edit(!)
So I got almost everything in order, baring one thing which is case 2 for the remove method.
//Case 2: If node has only one child, copy the value of the child to your node, and assign LeftChild or RightChild to null (as is the case)
if (RightChild != null && LeftChild == null)
{
if (value.CompareTo(this.Parent._value) > 0)
{
Parent.RightChild = RightChild;
RightChild = null;
}
}
if (RightChild == null && LeftChild != null)
{
if (value.CompareTo(Parent._value) < 0)
{
Parent.LeftChild = LeftChild;
LeftChild = null;
}
}
Basically, I am completely unable to replace the original node. If I have have
4 - 3 - 2 ( preorder ) and I want to remove 3 then I can do that and get 4 - 2.
However, if I want to remove 4 , it won't do anything, though it only got one child. I am think thats because it doesn't have a parent, but I am unsure of how to get around that. Any ideas?
Binary Search Tree
There are three possible cases to consider:
Deleting a leaf (node with no children): Deleting a leaf is easy, as we can simply remove it from the tree.
Deleting a node with one child: Remove the node and replace it with its child.
Deleting a node with two children: Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node or its in-order predecessor node, R. Replace the value of N with the value of R, then delete R.
Add one more condition to your remove method whose pseudo-code is:
if (value.CompareTo(Parent.Value) == 0){
//Case 1: If node has no children, then make Parent = null
// Case 2: If node has only one child, copy the value of the child to your node, and assign LeftChild or RightChild to null (as is the case)
//Case 3: Find the in-order successor, copy its value to the current node and delete the in-order successor.
}

Dynamic derive Generic Type Parameter

I am using a recursive function for a object tree. That is, my object collection is like:
Object1
--Object2
----Object3
------Object4
All objects inherits from a base object (abstract class), where has a Validate() method, and its collection inherits from ITreeCollection. I have written a recursive function to perform that:
private bool Validate<T>(ITreeCollection items) where T : TreeNodeBase
{
foreach (var itm in items as Collection<T>)
{
if (((TreeNodeBase)itm).Items != null)
{
return Validate<T>(((TreeNodeBase)itm).Items);
}
else return true;
}
return true;
}
How can I derive the the type parameter T for the inner function (i.e. return Validate<T>(((TreeNodeBase)itm).Items))
Firstly, as it stands, you are not using the type parameter T so it could safely be removed. However I imagine you might want to do some type specific validation so this is perhaps not that helpful a suggestion. But, without example of what you want to do with T it's difficult to make suggestions.
Anyhow, here's one approach of what I think you are trying to do:
private bool Validate(ITreeCollection items)
{
foreach (TreeNodeBase node in (IEnumerable) items)
{
// validate the node itself first
if (!Validate(node))
{
return false;
}
if (node.Items != null)
{
// validate its children
if (!Validate(node.Items)
{
return false;
}
}
}
return true;
}
private bool Validate(TreeNodeBase node)
{
if (node is BananaNode)
{
var bananaNode = (BananaNode) node;
//TODO do BananaNode specific validation
}
else if (node is AppleNode)
{
var appleNode = (AppleNode) node;
//TODO do AppleNode specific validation
}
else
{
throw new ArgumentOutOfRangeException("Cannot validate node of type '" + node.GetType().Name + "'.");
}
}
You could get snazzy with the dynamic keyword and get rid of some of this type checking but it does get a bit confusing and I'd advise against it:
private bool Validate(ITreeCollection items)
{
foreach (TreeNodeBase node in (IEnumerable) items)
{
// validate the node itself first
if (!Validate((dynamic) node)) // this will call the most appropriate version of Validate
{
return false;
}
if (node.Items != null)
{
// validate its children
if (!Validate(node.Items)
{
return false;
}
}
}
return true;
}
private bool Validate(BananaNode node)
{
//TODO do BananaNode specific validation
}
private bool Validate(AppleNode node)
{
//TODO do AppleNode specific validation
}
private bool Validate(TreeNodeBase node)
{
throw new ArgumentOutOfRangeException("Cannot validate node of type '" + node.GetType().Name + "'.");
}

How to write a method that will dynamically search treenodes of a treeview?

I am creating a (recursive) method that will allow me to specify a root treenode, a treenode property, and a value to match against.
SearchAllTreeNodes(rootNode, Tag, "foo");
In this example, the intended method would return the TreeNode whose Tag property matches the string "foo".
I'm not sure how to handle the second argument to the method:
public static TreeNode SearchAllTreeNodes(TreeNode rootNode, /* ?? */, string Value)
{
/* ... */
}
How can I specify which property of an object I want to check? Further, is there a recommended way to handle multiple value types or should I simply create some overloads for those (int, bool)?
Edit:
Thanks to the answers provided I was able to complete the following method:
public static TreeNode SearchAllTreeNodes(TreeNodeCollection nodeCollection, Func<TreeNode, bool> match)
{
foreach (TreeNode tn in nodeCollection)
{
if (match(tn)) return tn;
if (tn.Nodes.Count <= 0) continue;
TreeNode f = SearchAllTreeNodes(tn.Nodes, match);
if (f != null) return f;
}
return null;
}
Invoked like so:
SearchAllTreeNodes(treeView.Nodes, node => node.Tag != null && (string)node.Tag == "foo")
or:
SearchAllTreeNodes(treeView.Nodes, node => node.Tag != null && (int)node.Tag == 42)
I'd go for a delegate (in which you encapsulate the comparison with the desired value):
public static TreeNode SearchAllTreeNodes(TreeNode rootNode, Func<TreeNode, bool> match)
{
if (match(rootNode))
{
/* ... */
}
}
Invoke:
SearchAllTreeNodes(rootNode, node => node.Tag == "foo");
I agree with the other answers in that you should take a delegate to perform the match, but if you really want to take the approach of specifying a property and value, you can use reflection and specify the the property name as a string:
public static TreeNode SearchAllTreeNodes(TreeNode rootNode, string property, string value)
{
PropertyInfo propertyInfo = treeNode.GetType().GetProperty(property);
if (propertyInfo.GetValue(treeNode, null).ToString() == value)
{
/* Do stuff */
}
}
public static void Main(string[] args)
{
/* ... */
SearchAllTreeNodes(someNode, "Tag", "foo");
}
Of course, keep in mind that reflection is slow, it would not be recommended to run the above code over a large number of comparisons. You can speed it up by keeping hold of the PropertyInfo object and reusing it, rather obtaining it every time.
public static TreeNode SearchAllTreeNodes(TreeNode rootNode, Func<TreeNode, bool> matchCriteria, string Value)
{
if (matchCriteria != null )
{
var result = matchCriteria(rootNode);
}
}

Categories

Resources