I'm working on a testing platform app for students. Since the question can have one or multiple correct answers, I need radio buttons/checkboxes for selecting the right one(s). I would like to implement an abstract class with an Add method. From it, derive two classes, each of them containing an array of RaddioButtons or Checkboxes. Is there a better way to do this than the one listed below? I mean, can the add method be put in the abstract class?
public class AnswerForm
{
public static int no;
public AnswerForm()
{
no=0;
}
}
public class RadioButtonClass:AnswerForm
{
RadioButton[] vector;
public void Add(RadioButton rbutton)
{
vector[no++] = rbutton;
}
}
public class CheckBoxClass : AnswerForm
{
CheckBox[] vector;
public void Add(CheckBox cbox)
{
vector[no++] = cbox;
}
}
I also have two vectors in which I put a fixed number of elements, RadioButtons and Checkboxes. These elements exist in the Windows Form Form1.cs[design]. What I would like to do is pass one an element of type AnswerForm to a function and in the function, based on what type of question I have, allocate memory to my AnswerForm object for one of the derived classes. Also, it might be easier if the Add method would have as parameter a s string, and vector[no++].Text=s;
The prototype of the function:
public void readQuestions(RichTextBox richTextBox, AnswerForm answerForm)
Here I'm parsing an XML file and put the objects in a List. The XML contains Questions, each having a type(multiple or single answer), the text which goes to the richTextBox, and the answers. Next i'm looping through the question list and check question's type. If multiple answers, then put each answer in a CheckBox.Text. Else, put it in a RadioButton.Text. Before assigning the text to each WinForm element, I would like to allocate the corresponding object type(RadioButtonClass or CheckBoxClass) and then use the add method for each answer of the current question. That is why I thought of inheritance, abstractization an polymorphism.
This is how it look like now:
public void readQuestions(RichTextBox richTextBox, AnswerForm answerForm)
{
var file = XDocument.Load("QuestionsTest.xml");
var subject = new Subject();
subject.Name = (string)file.Root.Attribute("Subject");
var questions = from question in file.Root.Elements("Question")
select new Question
{
NumberOfCorrectAnswers=(int)question.Attribute("NumberOfAnswers"),
Text = (string)question.Element("Text"),
Answers = new List<Answer>(
from answers in question.Element("Answers").Elements("Answer")
select new Answer
{
Text = (string)answers
})
};
using (var db = new TestingPlatformContext())
{
db.Subjects.Add(subject);
foreach (var question in questions)
{
//Console.WriteLine("Subject: {0}\n Text: {1}", question.Subject, question.Text);
richTextBox.Text = question.Text;
//db.Questions.Add(question);
foreach (var answer in question.Answers)
//Console.WriteLine("Answer: {0}", answer.Text);
if (question.NumberOfCorrectAnswers != 1)
{
answerForm = new CheckBoxClass();
answerForm.Add(answer.Text);
//db.Answers.Add(answer);
}
else
{
answerForm = new RadioButtonClass();
answerForm.Add(answer.Text);
}
}
}
}
Yes, you can move the Add() method to parent class, using generic:
public class AnswerForm<T>
{
private readonly IList<T> _list;
public AnswerForm()
{
_list = new List<T>();
}
public void Add(T button)
{
_list.Add(button);
}
}
public class RadioButtonClass:AnswerForm<RadioButton>
{
}
public class CheckBoxClass : AnswerForm<CheckBox>
{
}
I made a few changes:
- Use list instead of array, it's more flexible in this case
- Use generic in parent class AnswerForm
A solution, much simple, would be like this:
public class AnswerForm
{
public static int no;
private RadioButton[] rbuttons;
private Checkbox[] checkboxes;
public AnswerForm()
{
no=0;
rbuttons = new RadioButton[]
{
radioButton1,radioButton2,radioButton3,radioButton4,radioButton5
};
checkboxes = new CheckBox[]
{
checkBox1,checkBox2,checkBox3,checkBox4,checkBox5,checkBox6
};
}
public void AddRadio(string s)
{
rbuttons[no++].Text=s;
}
public void AddBox(string s)
{
checkboxes[no++].Text=s;
}
}
But this is far from elegant.
Related
I have several different lists of objects, ie
List<Character> characters;
// ...
and some of those lists are of objects that implement the same interface:
public interface IDebugPrints
// ...
public class Character : IDebugPrints
// ...
I have a class where I would like to store a reference to a list (passed to it in its constructor) that implements IDebugPrints, ie
List<IDebugPrints> inList
So that later I can iterate through that list (in this case to print out debug information about the current entries in the original List).
I can't figure out how to do this. If I pass the List as IEnumerable, it makes a copy of the original list, which dosent work for me since objects are added and removed from the original list after that copy.
Any help is appreciated. I have a feeling this isnt possible based on a few other questions here on SO, but would appreciate confirmation.
EDIT:
Here is a bit more pseudo code:
public interface IDebugPrints
// ...
public class Character : IDebugPrints
// ...
public class StoreList
{
private List<IDebugPrints> internalList;
public StoreList( List<IDebugPrints> inList )
{
internalList = inList;
}
}
// The I have the various lists, for example
List<Character> characters;
// ...
// And I want to pass that list
StoreList sl = new StoreList( characters );
This last line gives compile errors:
Cannot convert from System.Collections.Generic.List<Character> to Systems.Collections.Generic.List<IDebugPrints>
Pass List<Character> characters as a IEnumerable<IDebugPrint>. This works beginning with C# 4.
Make internalList and inList typed as IEnumerable<IDebugPrint>.
Reference types are never copied in C# (except if explicitly implemented and requested by the programmer). .NET has no general way to copy an arbitrary reference type instance.
This means that your variables of type IEnumerable<IDebugPrint> will refer to the existing modifiable list.
This compiles:
using Microsoft.VisualStudio.TestPlatform.UnitTestFramework;
using System.Collections.Generic;
public interface IDebugPrints
{
}
public class Character : IDebugPrints
{
}
public class StoreList
{
private List<IDebugPrints> internalList;
public StoreList(List<IDebugPrints> inList)
{
internalList = inList;
}
}
[TestClass]
public class Test1
{
[TestMethod]
public void MyTest()
{
var characters = new List<IDebugPrints>();
characters.Add(new Character());
var sl = new StoreList(characters);
}
}
It isn't possible to cast a List<x> to a List<y> directly, unless you're using casting methods like:
List<x> listX = listY.Cast<x>();
I would pass the List<Character> as an IList to the StoreList.
With the .OfType<>() extension, you can iterate the childs of the type given.
This way, the list isn't copied.
This way your StoreList can iterate it, not depending on the types you passed, as long the items are inherited from IDebugPrint, the ShowAllInfo will show the Info.
Here's an example:
public interface IDebugPrints
{
string Info { get; set; }
void ShowInfo();
}
public class Character : IDebugPrints
{
public string Info {get;set;}
public void ShowInfo()
{
Console.WriteLine(Info);
}
}
public class StoreList
{
private IList internalList;
public StoreList(IList inList)
{
internalList = inList;
}
public void ShowAllInfo()
{
// I love the OfType<>() extension, it only returns the items of type IDebugPrints.
foreach (var item in internalList.OfType<IDebugPrints>())
item.ShowInfo();
}
}
class Program
{
static void Main(string[] args)
{
List<Character> characters = new List<Character>();
characters.Add(new Character { Info = "Character 1" });
characters.Add(new Character { Info = "Character 2" });
// And I want to pass that list
StoreList sl = new StoreList(characters);
sl.ShowAllInfo();
Console.ReadKey();
}
}
I'm creating a child object from a parent object. So the scenario is that I have an object and a child object which adds a distance property for scenarios where I want to search. I've chosen to use inheritance as my UI works equivalently with either a search object or a list of objects not the result of a location search. So in this case inheritance seems a sensible choice.
As present I need to generate a new object MyObjectSearch from an instance of MyObject. At present I'm doing this in the constructor manually by setting properties one by one. I could use reflection but this would be slow. Is there a better way of achieving this kind of object enhancement?
Hopefully my code below illustrates the scenario.
public class MyObject {
// Some properties and a location.
}
public class MyObjectSearch : MyObject {
public double Distance { get; set; }
public MyObjectSearch(MyObject obj) {
base.Prop1 = obj.Prop1;
base.Prop2 = obj.Prop2;
}
}
And my search function:
public List<MyObjectSearch> DoSearch(Location loc) {
var myObjectSearchList = new List<MyObjectSearch>();
foreach (var object in myObjectList) {
var distance = getDistance();
var myObjectSearch = new MyObjectSearch(object);
myObjectSearch.Distance = distance;
myObjectSearchList.add(myObjectSearch);
}
return myObjectSearchList;
}
The base class needs to define a copy constructor:
public class MyObject
{
protected MyObject(MyObject other)
{
this.Prop1=other.Prop1;
this.Prop2=other.Prop2;
}
public object Prop1 { get; set; }
public object Prop2 { get; set; }
}
public class MyObjectSearch : MyObject
{
public double Distance { get; set; }
public MyObjectSearch(MyObject obj)
: base(obj)
{
this.Distance=0;
}
public MyObjectSearch(MyObjectSearch other)
: base(other)
{
this.Distance=other.Distance;
}
}
This way the setting of properties is handled for all derived classes by the base class.
You can use reflection to copy properties.
public class ChildClass : ParentClass
{
public ChildClass(ParentClass ch)
{
foreach (var prop in ch.GetType().GetProperties())
{
this.GetType().GetProperty(prop.Name).SetValue(this, prop.GetValue(ch, null), null);
}
}
}
There is no easy way to do this, unfortunately. As you said, you would either have to use reflection, or create a "Clone" method that would generate a new child object using a parent object as input, like so:
public class MyObjectSearch : MyObject {
// Other code
public static MyObjectSearch CloneFromMyObject(MyObject obj)
{
var newObj = new MyObjectSearch();
// Copy properties here
obj.Prop1 = newObj.Prop1;
return newObj;
}
}
No matter what, you're either going to end up writing reflection code (which is slow), or writing each property out by hand. It all depends on whether or not you want maintainability (reflection) or speed (manual property copy).
A generic solution would be to serialize it to json and back. In the json-string is no information about the class name from which it was serialized.
Most people do this in javascript.
As you see it works well for pocco objects but i don't guarantee that it works in every complex case. But it does event for not-inherited classes when the properties are matched.
using Newtonsoft.Json;
namespace CastParentToChild
{
public class Program
{
public static void Main(string[] args)
{
var p = new parent();
p.a=111;
var s = JsonConvert.SerializeObject(p);
var c1 = JsonConvert.DeserializeObject<child1>(s);
var c2 = JsonConvert.DeserializeObject<child2>(s);
var foreigner = JsonConvert.DeserializeObject<NoFamily>(s);
bool allWorks = p.a == c1.a && p.a == c2.a && p.a == foreigner.a;
//Your code goes here
Console.WriteLine("Is convertable: "+allWorks + c2.b);
}
}
public class parent{
public int a;
}
public class child1 : parent{
public int b=12345;
}
public class child2 : child1{
}
public class NoFamily{
public int a;
public int b = 99999;
}
// Is not Deserializeable because
// Error 'NoFamily2' does not contain a definition for 'a' and no extension method 'a' accepting a first argument of type 'NoFamily2' could be found (are you missing a using directive or an assembly reference?)
public class NoFamily2{
public int b;
}
}
If a shallow copy is enough, you can use the MemberwiseClone method.
Example:
MyObject shallowClone = (MyObject)original.MemberwiseClone();
If you need a deep copy, you can serialize/deserialize like this: https://stackoverflow.com/a/78612/1105687
An example (assuming you write an extension method as suggested in that answer, and you call it DeepClone)
MyObject deepClone = original.DeepClone();
I first came accros this question when I was looking for doing this.
If you are able to work with C# 9 and record-classes. You only have to create a new constructor in the sub-class taking in a base class object and hand it over to the subclass:
public record MyObject {
...
}
public record MyObjectSearch :MyObject
{
public MyObjectSearch(MyObject parent) : base(parent) { }
...
}
Then you can create the child object like this:
MyObject parent = new();
MyObjectSearch m = new MyObjectSearch(parentObj) { Distance = 1.1};
Credits to https://stackoverflow.com/a/64573044/2582968
Seems natural for the base object to have constructor with parameters for its properties:
public class MyObject
{
public MyObject(prop1, prop2, ...)
{
this.Prop1 = prop1;
this.Prop2 = prop2;
}
}
So then, in your descendant object you can have:
public MyObjectSearch(MyObject obj)
:base(obj.Prop1, obj.Prop2)
This reduces duplication related to assignments. You could use reflection to automatically copy all properties, but this way seems more readable.
Note also, that if your classes have so much properties that you're thinking about automatizing of copying of the properties, then they are likely to violate the Single Responsibility Principle, and you should rather consider changing your design.
There are libraries to handle this; but if you just want a quick implementation in a few places, I would definitely go for a "copy constructor" as previously suggested.
One interesting point not mentioned is that if an object is a subclass, then it can access the child's private variables from the within the parent!
So, on the parent add a CloneIntoChild method. In my example:
Order is the parent class
OrderSnapshot is the child class
_bestPrice is a non-readonly private member on Order. But Order can set it for OrderSnapshot.
Example:
public OrderSnapshot CloneIntoChild()
{
OrderSnapshot sn = new OrderSnapshot()
{
_bestPrice = this._bestPrice,
_closed = this._closed,
_opened = this._opened,
_state = this._state
};
return sn;
}
NOTE: Readonly member variables MUST be set in the constructor, so you will have to use the child constructor to set these...
Although I don't like "up-sizing" generally, I use this approach a lot for analytic snapshots...
Okay, I have made an earnest effort to understand this over the past hour or so. So I am wondering if someone can explain this to me.
I'm trying to make a class in C# be Enumerable. Specifically, I'm trying to make it work with a foreach loop. I have a test going with a simple class, with takes in characters into the constructor.
EmployeeArray ArrayOfEmployees = new EmployeeArray('a','b','c');
foreach(char e in EmployeeArray) //Nope, can't do this!
{
Console.WriteLine(e);
}
//---Class Definition:---
class EmployeeArray
{
private char[] Employees;
public EmployeeChars(char[] e)
{
this.Employees = e;
}
//Now for my attempt at making it enumerable:
public IEnumerator GetEnumerator(int i)
{
return this.Employees[i];
}
}
I'm going to suggest that you stick with a simple List<>. This is a generic collection structure that does all the heavy lifting for you. Really, it does not make sense to make your own IEnumerables until you fully understand how the system works.
First, change your class to it represents a single item:
public class Employee
{
public string Name {get;set;}
//add additional properties
}
Then make a List<Employee> object
List<Employee> employees = new List<Employee>();
employees.Add(new Employee() { Name = "John Smith" });
foreach(Employee emp in employees)
Console.WriteLine(emp.Name);
If you really do want to get into making your own IEnumerables, look at the msdn page on them, which has a good example.
Is it something like this? And BTW you can't use the Class as the collection because it's a type. You need to use your declared variable to access it.
// You cant use EmployeeArray, instead use ArrayOfEmployees
foreach(char e in **EmployeeArray**)
{
Console.WriteLine(e);
}
Anyway here's how i did it.
class Program
{
static void Main(string[] args)
{
Collection collect = new Collection(new string[]{"LOL1","LOL2"});
foreach (string col in collect)
{
Console.WriteLine(col + "\n");
}
Console.ReadKey();
}
}
public class Collection : IEnumerable
{
private Collection(){}
public string[] CollectedCollection { get; set; }
public Collection(string[] ArrayCollection)
{
CollectedCollection = ArrayCollection;
}
public IEnumerator GetEnumerator()
{
return this.CollectedCollection.GetEnumerator();
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a list in one class. And I need to populate the list from another class. Then I need to access the list one or two other classes. I don't want to use static list. How is this done in C#. I tried my best. But not successful. Can anybody show example?.
use get I would suggest
This is where the list is
class A
{
private list<Objects> myList = new list<Objects>();
public list<Objects> getList()
{
return myList;
}
}
This is where you want to use it
class B
{
private list<Objects> myNewList = new list<Objects>();
A a = new A();
public void setList()
{
myNewList = a.getlist();
}
}
Something like this. Remember same namespace for classes to know each other, if in different files
This sounds like a job for a public property.
// I'm assuming a List of strings, fix accordingly
public class A
{
//Not autoimplemented to ensure it's always initialized
private List<string> items = new List<string>();
public List<string> Items
{
get { return items; }
set { items = value; }
}
}
public class AnyoneElse
{
void someMethod()
{
A someVar = new A();
someVar.Items.Add("This was added from outside");
MessageBox.Show(someVar.Items.First());
}
}
Access modifiers should be tweaked appropriately (they depend on your namespace structure, mostly. Also, are the class and the consumers in the same assembly or not ? Anyway, the point should be clear enough).
This is a basic example of what you need
public class YourOriginalClass
{
/// <summary>
/// The list you want to access
/// </summary>
public List<YourType> YourList {
get;
set;
}
}
// Here another class where you can use the list
public class YourSecondClass
{
public void EditMyList()
{
YourOriginalClass test = new YourOriginalClass();
test.YourList = new List<YourType>();
// then you can populate it
}
}
I created a class that's called UserSessionModel; in it I'm storing some data about the user and in particular I'm storing several json strings that are the results of queries and serializations.
I have several methods and properties in UserSessionModel that overall look like this:
public string SomeUserDataInJson1 { get; set; }
public string SomeUserDataInJson2 { get; set; }
.... 3 more properties like this
public int UserID { get; set; }
private void GetSomeUserDataInJson1
{
ObjectData1 TheObjectData1 = new ObjectData1();
UserQueries TheUserQueries = new UserQueries();
JavascriptSerializer TheSerializer = new JavascriptSerializer();
TheObjectData1 = TheUserQueries.GetData1(TheUserID);
this.SomeUserData1InJson = TheSerializer.Serialize(TheObjectData1);
}
This code is repeated 5 times, with the only change being the ObjectData, the name of the query and the property SomeUserData that's getting set.
Is there a way to make this "better" with an interface or some other c# tools?
Thanks.
Ok, lets assume the following regarding to your example: You're having data for processing with queries defined differently per user (userId).
Our data container class... very simple here, contains only a string.
public class Data
{
public string Content { get; set; }
}
Next step, lets have a look at the query... could be using that interface (could use events, for the response but lets keep it simple here).
public interface IQuery
{
Data Process(Data data);
}
You could have a relation to the user by adding the userId to the IQuery interface but I would prefer to have another interface to solve that:
public interface IUserQueryProvider
{
IEnumerable<IQuery> GetQuerysForUser(uint id);
}
This way you can alter your user to query resolving in a seperate place.
You'll have a serializer/converter, too. Ok, lets make an Interface here for serialization of (processed) data.
public interface ISerializer
{
string Serialize(Data data);
}
Now, lets have a look at implementations, first of all the serializer... doesn't do anything magical here and you should fill in the things you need for serialization of objects (JSON, ...)
public class JavascriptSerializer : ISerializer
{
public string Serialize(Data data)
{
return data.Content; //whatever you want do instead for serialization
}
}
Now let us go to our Queries. I assume you're not very familiar with design patterns and you're meaning something like a Command Pattern instead (for processing jobs, see my link in the comments for more info about design pattern). 3 implementations follows as samples:
public class ReplaceQuery : IQuery
{
private readonly string match;
private readonly string text;
public ReplaceQuery(string match, string text)
{
this.match = match;
this.text = text;
}
public Data Process(Data data)
{
return data.Content.Contains(match) ? new Data {Content = data.Content.Replace(match, text)} : null;
}
}
public class GreetingToQuery : IQuery
{
private readonly string greeting;
private readonly string place;
public GreetingToQuery(string greeting, string place)
{
this.greeting = greeting;
this.place = place;
}
public Data Process(Data data)
{
return data.Content.Contains(greeting) ? new Data {Content = data.Content + place + "."} : null;
}
}
public class LineEndingQuery : IQuery
{
public Data Process(Data data)
{
return data.Content.LastIndexOf(".", StringComparison.Ordinal) == data.Content.Length - 1 &&
data.Content.Length > 0
? new Data {Content = "\n"}
: null;
}
}
If we want to resolve which querys belongs to a user we need our IUserQueryProvider implementation. It is nothing more than a dictionary in this case (but could be easyly switched to other implementations).
public class SampleQueryProvider : Dictionary<uint, IEnumerable<IQuery>>, IUserQueryProvider
{
public IEnumerable<IQuery> GetQuerysForUser(uint id)
{
IEnumerable<IQuery> queries;
TryGetValue(id, out queries);
return queries;
}
}
Last but not least... the glue for everything. I added another Interface here for our "generator engine".
public interface IScriptGenerator
{
event Action<string> Script;
void Generate(Data data, IEnumerable<IQuery> queries);
}
To make it more flexible I made the interface/implementation following a design principle introduced by Ralf Westphal called Event Based Components (EBC). Google is your friend if you are interested in this topic.
public class SampleScriptGenerator : IScriptGenerator
{
private readonly ISerializer serializer;
public event Action<string> Script;
public SampleScriptGenerator(ISerializer serializer)
{
this.serializer = serializer;
}
public void Generate(Data data, IEnumerable<IQuery> queries)
{
foreach (string serialized in from query in queries select query.Process(data) into result where result != null select serializer.Serialize(result))
{
OnSerialize(serialized);
}
}
private void OnSerialize(string serialized)
{
var handler = Script;
if (handler != null) handler(serialized);
}
}
And now lets put it all together and let us fly:
static void Main()
{
var generator = new SampleScriptGenerator(new JavascriptSerializer());
generator.Script += Console.Write; // bind to console output here
var queryProvider = new SampleQueryProvider
{
{
1, // user with id 1
new List<IQuery>
{
new ReplaceQuery("<name>", "frenchie"),
new GreetingToQuery("bonjour", "the universe"),
new LineEndingQuery()
}
},
{
2, // user with id 2
new List<IQuery>
{
new ReplaceQuery("<name>", "stegi"),
new GreetingToQuery("hello", "the world"),
new LineEndingQuery()
}
}
};
var data1 = new Data {Content = "My name is <name>."};
var data2 = new Data {Content = "I say hello to "};
var data3 = new Data {Content = "I say bonjour to "};
var data4 = new Data {Content = "."};
// you cold combine data and user query execution into lists and loops, too
generator.Generate(data1, queryProvider.GetQuerysForUser(1));
generator.Generate(data2, queryProvider.GetQuerysForUser(1));
generator.Generate(data3, queryProvider.GetQuerysForUser(1));
generator.Generate(data4, queryProvider.GetQuerysForUser(1));
generator.Generate(data1, queryProvider.GetQuerysForUser(2));
generator.Generate(data2, queryProvider.GetQuerysForUser(2));
generator.Generate(data3, queryProvider.GetQuerysForUser(2));
generator.Generate(data4, queryProvider.GetQuerysForUser(2));
Console.ReadKey();
}
}
You should see something like:
My name is frenchie.
I say bonjour to the universe.
My name is stegi.
I say hello to the world.
As your homework... try to add your own query implementation and data to process. How would you add recursion here? ;-)
Firstly you should definitely use a List<string> or string[]. Then you can increase code space, and extensibility. You can loop through and load data into the list like your doing there. Another thing, did you mean TheQueries by TheUserQueries, as I can't see the latter declared or the former used.
If you ever find yourself creating more than two similar property like you have done, you should probably use a List.
Secondly, the point of an interface is to force an object to implement certain methods etc. that can then be called and accessed in other classes. If that will help you, then you can put your method in an interface. Otherwise there's really no point.