How to compare objects in C# - c#

How do you compare objects in C#. Here is a sample of my code
namespace MyService
{
public static class CurrentVCobj
{
public static string id { get; set; }
public static string Month { get; set; }
public static string Year { get; set; }
}
public static class ResponseVCObj
{
public static string id { get; set; }
public static string Month { get; set; }
public static string Year { get; set; }
}
}
I would like to assign values to the above objects (CurrentVCobj and ResponseVCObj) then compare(TRUE OR FALSE) them in the method below to see if they are equal
public static void compareMethood(IEnumerable<tets> vc )
{
var myvar = vc;
var mycac = rep.populateDict();
foreach (var item in myvar)
{
ResponseVCObj.id = item.id;
ResponseVCObj.Month = DateRange.Month;
ResponseVCObj.Year = DateRange.Year;
CurrentVCobj.id = currentV.Select(d => d.Value.id).ToString() ;
CurrentVCobj.Month = currentV.Select(d => d.Value.Month).ToString();
CurrentVCobj.Year = currentV.Select(d => d.Value.Year).ToString();
//COMPARE OBJECTS HERE
}
}

Try this:
if (ResponseVCObj.Equals(CurrentVCobj))
{
...
}
else
{
...
}

First off, is there any reason you are using static classes? Your sample code seems very bizarre to me. Your usage of LINQ seems unnecessary as well.
If you want to compare two different objects by something other than a simple reference check you need to override the Equals method.
A guide on that can be found here:
http://msdn.microsoft.com/en-us/library/ms173147(v=vs.80).aspx

The other answers are correct in noting that you should override object.Equals, and that you should remove the static modifier from the classes and their members.
In addition, you should consider
having the classes inherit from the same interface
having the classes inherit from the same base class; if this is possible, then you can implement the equality comparison in that base class
implementing IEquatable on each class or the base class; if there's no common base type then you probably want to implement it twice on each type -- IEnumerable<CurrentVCobj> and IEnumerable<ResponseVCObj>
the fact that when you compare strings for equality, the results may vary from one computer to the other, depending on the culture settings on that computer.

Related

Why is my method not being recognized by my generic object?

I've made a code that has an interface and an abstract class to make my main function to work with both objects. As I started to work around my function everything was working perfectly until I needed to get a function from the object itself.
My function is:
void addNode<T>(List<T> genericList) where T : IGraphs{
T genericNode = (T)Activator.CreateInstance(typeof(T));
genericNode.Number = contDirected;
if (genericList.Count > 0)
{
string connectedNode = "";
while (!connectedNode.Equals("0") && genericList.RemainingNodesExist(undirectedGraphs, genericNode))
{
}
}
}
}
Obviously the function is not yet finished but the problem is on my last "while". As I try to get the method "RemainingNodesExist", the IDE gives me an advice saying that List does not have a definition for the method. Im not sure why is that since I have it on my classes:
public interface IGraphs
{
public int Number { get; set; }
public List<int> LinkedNumbers { get; set; }
}
public abstract class AbstractGraphs<T>
{
public abstract bool RemainingNodesExist(List<T> list, T node);
}
And on the classes that inherit from those above:
public class DirectedGraph: AbstractGraphs<DirectedGraph>, IGraphs
{
public int Number { get; set; }
public List<int> LinkedNumbers { get; set; }
public DirectedGraph()
{
Number = Number;
LinkedNumbers = new List<int>();
}
public override bool RemainingNodesExist(List<DirectedGraph> list, DirectedGraph node)
{
int numbersConnected = node.LinkedNumbers.Count;
if (numbersConnected != list.Count)
{
return true;
}
return false;
}
public UndirectedGraph()
{
Number = Number;
LinkedNumbers = new List<int>();
}
public int Number { get; set; }
public List<int> LinkedNumbers { get; set; }
public override bool RemainingNodesExist(List<UndirectedGraph> list, UndirectedGraph node)
{
int numbersConnected = node.LinkedNumbers.Count;
if (numbersConnected != list.Count)
{
return true;
}
return false;
}
To better summarize whats my goal...
I have 2 objects that are exactly the same in properties, but the methods will probably be different in some situations. I used the generic class T because the program will use a list of objects not yet defined that can be any of the two objects mentioned above. What I want my program to do is run the "addNode" function and run the method of both objects based on their type.
Has anyone had to deal with a similar problem or could give me some direction on how to solve this?
I am very suspicious of this code base, it looks way way too complicated.
But to answer your specific question
while (!connectedNode.Equals("0") && genericList.RemainingNodesExist(undirectedGraphs, genericNode))
attempts to call a method on genericList, thats a List<XXX> passed as a parameter
That method (RemainingNodesExist) is defined here
public abstract class AbstractGraphs<T>
{
public abstract bool RemainingNodesExist(List<T> list, T node);
}
Its a method of a class called AbstractGraphs<T>
Which has no relation to List<AnythinG>
Its hard to say what you need to change because this is such a convoluted set of classes.
Maybe if you can explain why you think that method would be callable on a list that might make it clearer

Reference known property in (List<someClass>)someObject

have tried some searches. Probably my lack of knowledge that I'm not using the right search terms or perhaps just not understanding the answers.
I have a method that is being passed an object, which I want to output a particular value to a text file.
I already know the object will be a List< someClass > of a few different possible classes (customers/employees/items etc). But all of the classes contain the same string property (e.g.) string idNumber.
So something like this:
public static void OutputFile(object myInput)
{
foreach (someGenericObject in (List<anyType>)myInput)
{
string textToOutput = someGenericObject.idNUmber;
//output the text to somewhere else here
}
}
I feel like as long as I know that it will always contain a this "idNumber" property regardless of the type, that I should be able to reference it somehow. But I just can't seem to get my head around it?
The error I typically get is something like:
Cannot cast List< Employee > to List< object > etc.
Thanks in advance
As I suggested in the comments, if you have the ability to modify these classes, you can have them all inherit from an interface IHasIdNumber with an idNumber property.
Your method would then become:
public static void OutputFile(IEnumerable<IHasIdNumber> myInput)
{
foreach (var item in myInput)
{
string textToOutput = item.idNUmber;
//output the text to somewhere else here
}
}
There are a few ways you can solve this.
Recommended way: Implement common interface:
public interface INumberable { // I'm sure you can come up with a better name...
string IDNumber { get; set; }
}
And then all the possible classes that can be passed into the method will implement INumberable. Your method can then look like this:
public static void OutputFile(List<INumerable> myInput)
{
foreach (var someGenericObject in myInput)
{
string textToOutput = someGenericObject.idNUmber;
//output the text to somewhere else here
}
}
Not-so-recommended way: Reflection:
Type t = someGenericObject.GetType();
var p = t.GetProperty("idNumber");
string theStringYouWant = (string)p.GetValue(someGenericObject);
Note that this is not very safe.
You can use [dynamic].
foreach (var someGenericObject in (dynamic)myInput)
{
//...
}
If all your classes have the same property you want to access in foreach loop you can do in via interface.
public interface ISmth {
int MyProperty { get; set; }
}
public class Student : ISmth {
public int MyProperty { get; set; }
}
public class Employee : ISmth {
public int MyProperty { get; set; }
}
public static void DoSmth(object myObj) {
foreach(ISmth item in (List<object>)myObj) {
Console.Write(item.MyProperty);
}
}
List<Student> stdList = new List<Student>();
DoSmth(stdList.Cast<object>().ToList());

I want to fill class members with default if they are missing, using generic in C#

I have multiple web requests that post JSON object and I have serializable classes with all the fields. For example:
[Serializable]
public class RequestOne()
{
public string date;
public string information;
public string subject;
}
[Serializable]
public class RequestTwo()
{
public int ID;
public string Data;
public string message;
}
And my method takes partially filled request class and I want to fill in any missing fields with default values declared in constant class.
And I want to avoid writing each method with for each request, like :
public static void FillWithDefault(this RequestOne request)
{ if (request.date.Equals(null)) request.date = DEFAULT_DATE;
if (request.information.Equals(null)) request.information = DEFAULT_INFO;
if (request.subject.Equals(null)) request.subject = DEFAULT_SUBJECT;
}
public static void FillWithDefault(this RequestTwo request)
{
//do the same for the fields in RequestTwo
}
I want to know if there is any way to achieve this using generic?
I want to do something similar to this:
public static void FillWithDefault<T>(this T request)
{
if(typeof(T) == typeof(request))
{
//check each member in request and fill with default if it's null
}
.
.
.
}
So that in my main method I can use like this :
RequestOne request = new RequestOne();
request.FillWithDefault();
RequestTwo request2 = new RequestTwo();
request2.FillWithDefault();
Can someone please help with idea on this? Am I overthinking on this? I'm new to generic so please feel free to advise on my code.
Edit
Sorry guys, I did not mention that I will be using this method for test automation. Those request contracts cannot be changed since it's by design. Sorry again for the confusion!
Use constructors. Also make use of properties. Don't gather the default filling code to one place, it's the responsibility of the classes so keep them there.
[Serializable]
public class RequestOne()
{
public string date { get; set; };
public string information { get; set; };
public string subject { get; set; };
public RequestOne()
{
Date = DEFAULT_DATE;
Information = DEFAULT_DATE;
Subject = DEFAULT_SUBJECT;
}
}
[Serializable]
public class RequestTwo()
{
public int ID { get; set; };
public string Data { get; set; };
public string Message { get; set; };
public RequestTwo()
{
Data = DEFAULT_DATA;
message = DEFAULT_MESSAGE;
}
}
Generics are used when the types have common operations/properties defined so you can apply the same routine for each type in one place instead of declaring different methods for each type.
However in this case, you have two different types with different properties, so I would not use generics here. You can achieve it with manual type checking and using reflection to get properties and set them but it's not a good way and definitely wouldn't be a good usage of generics.
Overloading is the way to go.
you can use property
[Serializable]
public class RequestOne()
{
private string _date;
public string date { get { return _date;} set { _date = value ?? DEFAULT_DATE; }};
public string information; // same here
public string subject; //same here
}

How to store a list of different generic things in C#

Say for example I have this base class
class Mangler<TInput, TOutput>
{
}
And then I make a couple of derived classes
class StringToBytesMangler : Mangler<string, byte[]>
{
}
class IntToGuidMangler : Mangler<int, Guid>
{
}
How do I store a collection of Mangler<TInput, TOutput> where TInput and TOutput may be different at any given time?
i.e.
List<Mangler<?, ?>> list = new List<Mangler<?, ?>>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
Is this possible?
You need a non-generic Mangler base class.
List<Mangler> list = new List<Mangler>();
list.Add(new StringToBytesMangler());
list.Add(new IntToGuidMangler());
Of course, this means you also need to have non-generic versions of the methods that depend on TInput or TOutput.
If I understood the question correctly, this is not possible the way you tried it. The types StringToBytesMangler and IntToGuidMangler do not derive from the same type. You could introduce a shared base type, but I recommend reconsidering the design - even if they could be stored in the same collection, they would syntactically have nothing in common (at least it isn't shown in the question).
The whole idea behind generics is to have generic code so type of that class can be treated the same. From what you have posted, it is not easy to see what generic code you have.
Below I have a class that has some generic code:
class Mangler<TInput, TOutput>
where TInput: ITInput
where TOutput: ITOutput {
public TInput Input { get; set; }
public TOutput Output { get; set; }
public bool IsInputAGuid() {
if (Guid.Parse(this.Input.SomeThing) == this.Output.SomeGuid ) {
return true;
}
return false;
}
}
You can see in the above class, when it parses a string to a Guid from this.Input.Something and then it performs == on it with this.Ouput.SomeGuid, the compiler is happy because we have made the constraint that TInput must implement the interface ITInput so the compiler knows this line will work and Input will have Something as a string property:
Guid.Parse(this.Input.SomeThing)
The compiler does not care what the concrete type is so long as Something is available. It is the same idea for TOuput but the compiler expects that it implements ITOutput so it expects a Guid in SomeGuid. This is why the compiler is happy to parse a string to a guid and then perform the == operator on it with another thing which is also a Guid.
Here are the interfaces and some classes which implement them:
internal interface ITInput {
string SomeThing { get; set; }
}
internal interface ITOutput {
Guid SomeGuid { get; set; }
}
internal class AnotherInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeInput : ITInput {
public string SomeThing { get; set; }
}
internal class SomeOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
internal class SomeOtherOutput : ITOutput {
public Guid SomeGuid { get; set; }
}
Finally, here is the usage where we can treat these generically:
var manglers = new List<Mangler<ITInput, ITOutput>>();
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new SomeInput(), Output = new SomeOutput() } );
manglers.Add( new Mangler<ITInput, ITOutput>
{ Input = new AnotherInput(), Output = new SomeOutput() } );
foreach( var thisMangler in manglers ) {
var input = thisMangler.Input;
var output = thisMangler.Output;
var success = thisMangler.IsInputAGuid();
}
You can see in the foreach regardless of the concrete type, we can call Input, Output and IsInputAGuid() on all of them.
So in your code find what code is generic and then apply the above technique to it. You can either use interfaces or a base class for your constraints.

Distinct List of object in C#

I have to distinct list of object but NOT only by ID because sometimes two different objects have same ID.
I have class:
public class MessageDTO
{
public MessageDTO(MessageDTO a)
{
this.MsgID = a.MsgID;
this.Subject = a.Subject;
this.MessageText = a.MessageText;
this.ViewedDate = a.ViewedDate;
this.CreatedDate = a.CreatedDate;
}
public int? MsgID { get; set; }
public string Subject { get; set; }
public string MessageText { get; set; }
public System.DateTime? ViewedDate { get; set; }
public System.DateTime? CreatedDate { get; set; }
}
How I can distinct list of:
List<MessageDTO> example;
Thanks
Use LINQ.
public class MessageDTOEqualityComparer : EqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO a, MessageDTO b)
{
// your logic, which checks each messages properties for whatever
// grounds you need to deem them "equal." In your case, it sounds like
// this will just be a matter of iterating through each property with an
// if-not-equal-return-false block, then returning true at the end
}
public int GetHashCode(MessageDTO message)
{
// your logic, I'd probably just return the message ID if you can,
// assuming that doesn't overlap too much and that it does
// have to be equal on the two
}
}
Then
return nonDistinct.Distinct(new MessageDTOEqualityComparer());
You can also avoid the need for an extra class by overriding object.Equals(object) and object.GetHashCode() and calling the empty overload of nonDistinct.Distinct(). Make sure you recognize the implications of this decision, though: for instance, those will then become the equality-testing functions in all non-explicit scopes of their use. This might be perfect and exactly what you need, or it could lead to some unexpected consequences. Just make sure you know what you're getting into.
I you want to use other properties, you should implement IEqualityComparer interface. More on: msdn
class MsgComparer : IEqualityComparer<MessageDTO>
{
public bool Equals(MessageDTO x, MessageDTO Oy)
{
}
// If Equals() returns true for a pair of objects
// then GetHashCode() must return the same value for these objects.
public int GetHashCode(MessageDTO m)
{
//it must br overwritten also
}
}
Then:
example.Distinct(new MsgComparer());
You could also overwrite Equals in MessageDTO class:
class MessageDTO
{
// rest of members
public override bool Equals(object obj)
{
// your stuff. See: http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx
}
public override int GetHashCode()
{
}
}
Then it's enough:
example.Distinct();
You could use the extension method DistinctBy from the MoreLinq library:
string[] source = { "first", "second", "third", "fourth", "fifth" };
var distinct = source.DistinctBy(word => word.Length);
See here:
I recommend you using solution of #Matthew Haugen
In case you don't want to create a new class for that, there is a way to use LINQ by grouping you list by distinct field(s) then select the first item on this group. For example:
example.(e => new { e.MsgID, e.Subject }).Select(grp => grp.FirstOrDefault());

Categories