Why is my method not being recognized by my generic object? - c#

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

Related

How to correctly implement this IComparable?

I have problems wit hthe implementation of a generic sorting algorithm.
We need to implement quicksort and selection sort, and a class which should be sortable using these functions. The functions should be generic, and thus work on other classes as well.
I tested the quicksort. It works perfectly on a List. However, when trying to execute it on my own comparable class, it says:
There is no implicit reference conversion from 'SNIP' to 'System.IComparable'
Do you guys have any idea what the problem can be?
Here is my comparable class:
public class SNIP : IComparable
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(object obj)
{
if (obj == null) return 1;
SNIP oOtherPlank = obj as SNIP;
if (oOtherPlank != null)
return this.lCost.CompareTo(oOtherPlank.lCost);
else
throw new ArgumentException("Can only compare SNIPs.");
}
}
Thanks in advance!
Thanks to #Sweeper, the comparable is now fixed.
Like he said, I had to define my class better:
public class SNIP : IComparable<SNIP>
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(SNIP obj)
{
if (obj == null) return 1;
SNIP oOtherSnip= obj as SNIP;
if (oOtherSnip!= null)
return this.lCost.CompareTo(oOtherSnip.lCost);
else
throw new ArgumentException("Can only compare SNIPs.");
}
}
It is also important to note that this only works when the argument of the CompareTo method is actually of the right class. I tried defining the class as IComparable before, but it didn't work because the argument in CompareTo was set to an object. By changing both the CompareTo header and the class header, the problem is fixed and the sorting now works.
Thanks a lot :-)
You can implement generic IComparable<SNIP>, not IComparable which is very simple: this is always geater than null and if we compare with not null other we should check lCost.
public class SNIP : IComparable<SNIP>
{
private long lCost { get; set; }
public SNIP(long lCost)
{
this.lCost = lCost;
}
public int CompareTo(SNIP other) => other is null
? 1
: lCost.CompareTo(other.lCost);
}
then you can sort: note that since List<SNIP> is generic, the generic IComparable<SNIP> will be used on sorting.
List<SNIP> list = new List<SNIP>()
{
new SNIP(5),
new SNIP(1),
new SNIP(3),
};
list.Sort();

Create object with contructor based on enum flag

I'd like to create an object based on enum flag.
Here's the sample code:
public class Program
{
static void Main(string[] args)
{
var workflowBasic = new WorkflowBasic(WorkflowFlag.One);
if (workflowBasic.Flag == WorkflowFlag.One)
{
// create WorkflowOne workflow
}
else if (workflowBasic.Flag == WorkflowFlag.Two)
{
// create WorkflowTwo workflow
}
// TODO: rest action on created variable
}
}
public class WorkflowOne
{
public int Count { get; set; }
public WorkflowOne(int count)
{
Count = count;
}
}
public class WorkflowTwo
{
public int Count { get; set; }
public WorkflowTwo(int count)
{
Count = count;
}
}
public class WorkflowBasic
{
public WorkflowFlag Flag { get; set; }
public WorkflowBasic(WorkflowFlag flag)
{
Flag = flag;
}
}
public enum WorkflowFlag
{
One = 1,
Two = 2
}
So for WorkflowFlag.One it should creates WorkflowOne object and for WorkflowFlag.Two it should create WorkflowTwo.
Moreover, I'd like to create only one variable so I do not want to create some kind of:
if (workflowBasic.Flag == WorkflowFlag.One)
{
var objectTest = new WorkflowOne(1);
}
else if (workflowBasic.Flag == WorkflowFlag.Two)
{
var objectTest = new WorkflowTwo(2);
}
If it is something unclear, please let me know.
The requirement you are describing is a known as an "abstract factory" design pattern.You would give the enum to the abstract factory, and it would return you the relevant workflow object.
You might find that your workflow is a case of the "strategy" design pattern. I'd suggest they should all implement a common interface.
There are lots of ways of implementing this. One example would be to create an attribute which has the enum value as a parameter. Attach this attribute to each of your workflow classes with the relevant enum. The abstract factory can then use reflection to find the class which implements the workflow interface and also has the attribute with the required enum value.
And I would suggest adding unit tests to ensure that there is an implementation of each enum value.

(C#) Access/Modify Objects in a List

New here, I've been learning c# for about a month.
Anyway, I've been searching StackOverflow for a couple of days now and couldn't find a specific answer to my problem...
//Here's my Class
public class Guy
{
public static int ID { get; set; }
public static int LifeExpectancy { get; set; }
public static bool Living { get; set; }
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
What I'm trying to do is create a specific number of "someGuy" objects to then put them into a public list using this method...
public static List<Guy> Guys = new List<Guy>();
public static void makeSomeGuys(int howManyGuys)
{
for (int i = 0, i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
Guys.Add(New Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return;
}
Questions in order of importance:
How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
Can I search for an object in a list by using its parameters? (As opposed to doing something like... humanPopulation[number])
Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
I really only need the first question answered. The rest of them are just a bonus. Thanks!
First you need to remove the static modifier from the properties of the Guy class, i.e.:
public int ID { get; set; }
public int LifeExpectancy { get; set; }
public bool Living { get; set; }
because static causes the property to be an attribute of the class itself, rather than the instances of the class (the individual 'guys').
To access life expectancy of the first guy (the zeroth):
Console.WriteLine(Guys[0].LifeExpectancy);
To access life expectancy of the fifth guy:
Console.WriteLine(Guys[4].LifeExpectancy);
using System;
using System.Collections.Generic;
using System.Linq;
namespace test
{
public class Guy
{
private int m_ID;
private int m_LifeExpectancy;
private bool m_Living;
public int ID
{
get { return m_ID; }
set { m_ID = value; }
}
public int LifeExpectancy
{
get { return m_LifeExpectancy; }
set { m_LifeExpectancy = value; }
}
public bool Living
{
get { return m_Living; }
set { m_Living = value; }
}
public Guy(int id, int lifeExpectancy, bool living)
{
ID = id;
LifeExpectancy = lifeExpectancy;
Living = living;
}
}
public class MyFactory
{
public IList<Guy> MakeSomeGuys(int howManyGuys)
{
IList<Guy> localGuys = new List<Guy>();
for (int i = 0; i <= howManyGuys; i++)
{
int id = i;
int lifeExpectancy = 80;
bool alive = true;
localGuys.Add(new Guy(id, lifeExpectancy, alive));
Console.WriteLine("Made a new Guy {0}", id);
}
return localGuys;
}
}
public class program
{
public void Main()
{
MyFactory mf = new MyFactory();
IList<Guy> guys = mf.MakeSomeGuys(5);
//How do I access a specific object as well as its parameters? (Accessing from the list "Guys".)
int GetFirstGuyId = guys.FirstOrDefault().ID; //LEARN LINQ
//How do I access an object from this list in another class? (Not that I absolutely need to, I'm curious)
//you need to learn about object oriented encapsulation for better understanding.
//Can I search for an object in a list by using its parameters? (As opposed to doing something like...humanPopulation[number])
Guy guyById = guys.Where(g => g.ID == 5).FirstOrDefault(); // returns the first match (need to learn lambda expression)
//Should I create a new list for objects that have had their parameters modified? (As opposed to leaving it in the original list)
// you need to learn about passing values by value / reference (by reference you already changing the original!).
//Is it possible to remove items from a list? (Just in general, is that a thing people do? if so, why?)
//yes
guys.Remove(guyById);
}
}
}
You're likely new to C# and OO programming, so I've included some good links in this answer.
Regarding question 1 only:
Firstly, your Guy class properties aren't properly encapsulated. Make sure you properly scope the ID, LifeExpectancy and Living properties like shown in this article.
If you'd like to access a specific item, that is, a Guy with a particular ID, you'd be better off using an associative container like Dictionary.
If you're happy with the List container, you need to use the Find method on Guys as shown in the example at the link. You'll notice the term Predicate in the documentation, this link will elaborate.

List which accept only few types

Does there exist in any System namespace in C# a container, which can accept only some types?
For example I want to create my list in which I'll have only objects with type Class1 and int:
//accept only type Class1 and int;
MYLIST lst = new MYLIST(typeof(Class1), typeof(int));
lst.Add( 23 ); // OK
lst.Add( new Class1() ); // OK
lst.Add( "text" ); // wrong, not accepted type
Is something like that in .NET or I have to write it on my own? Thanks.
The C# type system does not allow you to express something like "either Class1 or int". Having said that, you can use overloads to get half of the way there:
class MyClass
{
private List<object> _items = new List<object>();
public void Add(int value) { _items.Add(value); }
public void Add(Class1 value) { _items.Add(value); }
...
}
The real tricky question is how you get things out, rather than how you put things in. There are several possibilities: get everything out as object (by implementing IEnumerable<object>), and maybe special methods like GetInt(int index) and GetClass1(int index).
The answer is NO, there is NO such list in C# and for VERY GOOD reason.
You could make a wrapper, but i'd advise against it.
public class CustomListWrapper< T, F>
{
private readonly List<object> internalList;
public CustomListWrapper()
{
this.internalList = new List<object>();
}
public void Add(object item)
{
if(!(item is T || item is F))
throw new Exception();
this.Add(item);
}
}
PS: before the downvote, for how to get the object out...well this is why this is a fairly bad idea, but you'd have to do an "is" on the type you get out to be able to cast it to the proper type.
Again, not exactly sure why you would EVER need to do this.
No. You will have to create your own. You can implement ICollection or IEnumerable or IList or whatever. You have lots of flexibility here. But bottom line, the answer is no, no such collection exists that allows you to limit the types in the collection to certain types automatically.
You cannot achieve this in a direct way. The item type of a List<T> must be a base type common to all the types you want to add to the list.
You could have a List<object> or a wrapper around a List<object> of cause. However, you would have to check at runtime if the items added to it are of the correct types and you would have to cast the items that you retrieve from the list to the correct type.
If you want to store different types in the same list, a good option would be to create an interface that all of these types must implement
public interface ICommonInterface
{
int Number { get; }
string Text { get; }
}
public Class1 : ICommonInterface
{
public int Number { get; set; }
public string Text { get; set; }
public string AnAdditionalProperty { get; set; }
}
public NumberWrapper : ICommonInterface
{
public NumberWrapper (int number)
{
this.Number = number;
this.Text = number.ToString();
}
public int Number { get; private set; }
public string Text { get; private set; }
}
public TextWrapper : ICommonInterface
{
public TextWrapper (string text)
{
this.Text = text;
int i;
Int32.TryParse(text, out i);
this.Number = i;
}
public int Number { get; private set; }
public string Text { get; private set; }
}
Then you can declare your list as
List<ICommonInterface> lst = new List<ICommonInterface>();
lst.Add(new Class1());
lst.Add(new NumberWrapper(77));
lst.Add(new TextWrapper("hello"));
Console.WriteLine(lst[0].Text);
why not just wrap a List<>, and make two add methods, one that accepts int, another that accepts Class1

How to compare objects in 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.

Categories