C# add item in abstract list - c#

For a project i am working with intherentance and an abstract class. with the help of a form i want to add items into a list, but get the following error during coding: cannot create an instance abstract type or interface 'Article'. does someone know how to fixt his?
articlemanager class:
private List<Article> items;
public ArticleManager()
{
items = new List<Article>();
}
public void addArticleEmergency(Article emergencyNews)
{
items.Add(emergencyNews);
}
abstract article class:
abstract class Article
{
public int id { get; private set; }
public string title { get; private set; }
public string text { get; private set; }
public Article(int id, string title, string text)
{
this.id = id;
this.title = title;
this.text = text;
}
public bool HasID(int id)
{
if (id == this.id)
{
return true;
}
return false;
}
public override string ToString()
{
return id + ": \r\n" + title + " \r\n " + text;
}
}
}
form:
private ArticleManager articalManagerAdd;
public Form1()
{
InitializeComponent();
this.articalManagerAdd = new ArticleManager();
}
private void btnMakeNewsArticle_Click(object sender, EventArgs e)
{
if(txtNewsNumber.Text == "" || txtNewsTitle.Text == "" || txtNewsText.Text == "" || !rbEmergency.Checked && !rbNormal.Checked )
{
lbSeeNewsItem.Items.Clear();
lbSeeNewsItem.Items.Add("Please fill in all the required information");
}
else
{
if (articalManagerAdd.GetArticle(Convert.ToInt32(txtNewsNumber.Text)) == null)
{
if (rbNormal.Checked)
{
articalManagerAdd.addArticleNormal(new Article(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text));
MessageBox.Show("Normal news article has been added");
}
else if(rbEmergency.Checked)
{
Article emergencyNews = new NewsArticle(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text);
MessageBox.Show("Emergency news article has been added");
}
}
else
{
lbSeeNewsItem.Items.Add("This id has already been used");
}
}
}

As the comments have mentioned, you cannot create an instance of an abstract class.
So your code new Article(Convert.ToInt32(txtNewsNumber.Text), txtNewsTitle.Text, txtNewsText.Text)) will not compile.
You can inherit from a non-abstract class so your NewsArticle class would be expected to work if you just removed the abstract modifier to your Article class.
Alternatively you could add a new sub-class of Article say NormalArticle and use that in your addArticleNormal method

Related

is this implementation of the Singleton and Object null Patterns Thread Safe?

Im trying to write a simple code to implement the Singleton and object null patterns.
the code should check if the new customer has a name, if yes put it in the real customer, and if not in the fakecustomer.
My focus in this question is: Is the Singleton pattern making my code thread safe in this case?
interface Icustomer
{
string Name { get; }
bool IsNull { get; }
}
class realcustomer : Icustomer
{
public string Name { get; set; }
public bool IsNull { get { return false; } }
public realcustomer(string name)
{
Name = name;
}
}
class fakecustomer : Icustomer
{
public string Name { get { return "customer not available"; } }
public bool IsNull { get { return true; } }
}
class checkifnull
{
public static Icustomer Getcustomer(string name)
{
if (string.IsNullOrEmpty(name))
{
return new fakecustomer();
}
else
{
return new realcustomer(name);
}
}
}
class Singleton
{
private int total = 0;
private static Icustomer cust;
private Singleton() { }
public static Icustomer makecust(string name)
{
if (cust == null)
{
if (string.IsNullOrEmpty(name))
{
cust = new fakecustomer();
}
else
{
cust = new realcustomer(name);
}
}
return cust;
}
public void add()
{
total++;
}
public int getTotal()
{
return total;
}
}
internal class Program
{
static void Main(string[] args)
{
Icustomer new_cust = Singleton.makecust("name");
}
}
each pattern works when implemented on its own, but now i'm trying to use both at the same time.

How can I access a string from another class in WPF

I got two scenes (windows), "MainWindow.xaml.cs" and "SecondaryWindow.xaml.cs". I also have one class "Control.cs".
Im trying to declare 2 different List<string>, and 2 public string in my Control.cs class.
It looks like this.
class Control
{
}
public class MyControl
{
List<string> NameList = new List<string>();
List<string> DescriptionList = new List<string>();
public string Name {
get { return Name; }
set { Name = value; }
}
public string Description {
get { return Description; }
set { Description = value; }
}
}
I want to access the different strings from Control.cs in my SecondWindow.xaml.cs class so that i can give them each a value from 2 textboxes in SecondWindow.
After this i want the string Name to save to NameList and string Description to DescriptionList.
Then I will send Name to a ListBox in "MainWindow" where i think it could be added something like this..?
private void Button_SaveAndReturn(object sender, RoutedEventArgs e)
{
var main = (MainWindow)Application.Current.MainWindow;
if (Example.Name != "" && Example.Description != "")
{
DateTime now = DateTime.Now;
main.listBox.Items.Add(string.Format("{0}: {1} ", Example.name, now));
this.Close();
}
Im trying my best to give out as much details as i can, tell me if there is anything else you need! Thanks in advance.
Edit
Here is my Control class:
class Control
{
List<string> NameList = new List<string>();
List<string> DescriptionList = new List<string>();
public static string Name
{
get { return Name; }
set { Name = value; }
}
public static string Description
{
get { return Description; }
set { Description = value; }
}
}
And my main class
private void Button_SaveAndReturn(object sender, RoutedEventArgs e)
{
List<string> nameList = new List<string>();
List<string> descriptionList = new List<string>();
var name = Control.Name;
var desc = Control.Description;
var main = (MainWindow)Application.Current.MainWindow;
if (name != "" && desc !="")
{
nameList.Add(name);
descriptionList.Add(desc);
DateTime now = DateTime.Now;
main.listBox.Items.Add(string.Format("{0}: {1} ", name, now));
this.Close();
}
else if (name== "")
{
MessageBox.Show("Please enter a name", "Name Error", MessageBoxButton.OK, MessageBoxImage.Error);
this.NameInput.Focus();
}
else
{
MessageBox.Show("Please enter some text", "Text Error", MessageBoxButton.OK, MessageBoxImage.Error);
this.TextInput.Focus();
}
Are you using WPF's MVVM capabilities? If you are, you can declare those lists and variables in a viewmodel common to all those classes; otherwise just mark all those properties as static so you can access them from the other classes like: MyControl.Name, MyControl.Description, etc...
I would use Prism for that.
Here is an example:
Class which will raise the event:
public class PublisherClass
{
public void UpdateName(string name)
{
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Publish(name);
}
}
Two classes will subscribe to this event:
public class SubscriberClass1
{
public string Name { get; set; }
public SubscriberClass1()
{
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
}
private void UpdateName(string name)
{
this.Name = name;
}
}
and
public class SubscriberClass2
{
public string Name { get; set; }
public SubscriberClass2()
{
Utility.EventAggregator.GetEvent<UpdateNameEvent>().Subscribe(UpdateName);
}
private void UpdateName(string name)
{
this.Name = name;
}
}
EventAggregator which is part of Prism.Events resides here:
public class Utility
{
public static EventAggregator EventAggregator { get; set; }
static Utility()
{
EventAggregator = new EventAggregator();
}
}
And the event is simply defined like this:
public class UpdateNameEvent : PubSubEvent<string>
{
}
Now give it a try:
static void Main(string[] args)
{
PublisherClass publisher = new PublisherClass();
SubscriberClass1 subscriber1 = new SubscriberClass1();
SubscriberClass2 subscriber2 = new SubscriberClass2();
publisher.UpdateName("Name1");
Console.WriteLine(subscriber1.Name);
Console.WriteLine(subscriber2.Name);
}
For this example i am using a string as parameter but you can replace that according to your needs.
Be it an MVVM approach or any other pattern, you can easily implement this kind of communication.
Install Prism.Core with the help of Nuget and you will get the reference to Prism dll.
That's about it.

C# add items to list from class then add list items to listbox

I'm a student in a C# class and this is my introductory assignment to Classes, so please bear with me. When the New button is pressed, a CPerson object will be created using the name and phone values and the object will be added to a List<>.
class CPerson
{
private string m_sName;
private string m_sPhone;
public string Name
{
get { return this.m_sName; }
set
{
this.m_sName = value;
}
}
public string Phone
{
get { return this.m_sPhone; }
set
{
this.m_sPhone = value;
}
}
}
public partial class Form1 : Form
{
private List<CPerson> PhoneNum = new List<CPerson>(); //<CPerson> or <string>?
public Form1()
{
InitializeComponent();
newbutton.Enabled = false;
changebutton.Enabled = false;
savebutton.Enabled = false;
}
private void newbutton_Click(object sender, EventArgs e)
{
changebutton.Enabled = true;
savebutton.Enabled = true;
PhoneNum.Add(new CPerson { Name = Namebox.Text + " : ", Phone = phonebox.Text });
listBox1.Items.Add(PhoneNum); //text = "Collection"
}
The assignment says "The CPerson ToString() override will be used to display the name and phone number in the listbox" as shown in the above image, which I don't necessarily understand, but I'm guessing I have to use something like this?
CPerson data = new CPerson();
data.ToString();
Either way, as the code is now, all I get in my listbox is "(Collection)". Any help would be appreciated!
That is asking to override the ToString() method. You can do it like this:
class CPerson
{
private string m_sName;
private string m_sPhone;
public string Name
{
get { return this.m_sName; }
set
{
this.m_sName = value;
}
}
public string Phone
{
get { return this.m_sPhone; }
set
{
this.m_sPhone = value;
}
}
public override string ToString()
{
return Name + ": " + Phone;
}
I did not get right the part of adding to the list, but I assume you can do the following using ToString():
listBox1.Items.Add(data.ToString());
Close...
class CPerson
{
private string m_sName;
private string m_sPhone;
public string Name
{
get { return this.m_sName; }
set
{
this.m_sName = value;
}
}
public string Phone
{
get { return this.m_sPhone; }
set
{
this.m_sPhone = value;
}
}
public override string ToString()
{
return Name + ": " + Phone;
}
}
}

Creating and using a custom List<T> in C#

I am trying to use a customized List were I have added a few additional tools. I want to apply this list to a long list of customized classes that I have created. All of the classes have an ID number and some of the tools in the List use the ID.
Here is a portion of my code that I am trying to use. I hope this help you understand my problem.
namespace Simple_Point_of _Sales_System
{
public class MyList<T> : List<T>
{
internal int SetID()
{
return this.Max(n => n.ID) + 1;
}
internal T Find(int ID)
{
return this.Find(n => n.ID == ID);
}
internal T Add(T n)
{
Read();
Add(n);
Write();
return n;
}
internal void Remove(int ID)
{
Read();
if (this.Exists(t => t.ID == ID)) RemoveAll(t => t.ID == ID);
else MessageBox.Show(GetType().Name + " " + ID + " does not exist.", "Missing Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
Write();
}
internal void Edit(int ID, T n)
{
Read();
if (this.Exists(t => t.ID == ID)) this[FindIndex(t => t.ID == ID)] = n;
else MessageBox.Show(GetType().Name + " " + ID + " does not exist.", "Missing Item", MessageBoxButtons.OK, MessageBoxIcon.Error);
Write();
}
internal MyList<T> Read()
{
Clear();
StreamReader sr = new StreamReader(#"../../Files/" + GetType().Name + ".txt");
while (!sr.EndOfStream)
Add(new T().Set(sr.ReadLine()));
sr.Close();
return this;
}
internal void Write()
{
StreamWriter sw = new StreamWriter(#"../../Files/" + GetType().Name + ".txt");
foreach (T n in this)
sw.WriteLine(n.ToString());
sw.Close();
}
}
public class Customer
{
public int ID;
public string FirstName;
public string LastName;
}
public class Item
{
public int ID { get; set; }
public string Category { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
public class MyClass
{
MyList<Customer> Customers = new MyList<Customer>();
MyList<Item> Items = new MyList<Item>();
}
}
I think your custom list needs to put on some constraints on the generic type to allow that. I would update your signature to something like
public class MyList<T> : List<T> where T : IIdentity { .... }
Here I used IIdentity as the interface defining ID, but it could also be a class.
To update your code I would do something like this:
public interface IIdentity
{
int ID { get; }
}
public class Customer : IIdentity
{
public int ID { get; set;}
public string FirstName;
public string LastName;
}
public class Item : IIdentity
{
public int ID { get; set; }
public string Category { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
I changed the ID in Customer to be a property instead of instance variable.

Casting to generic type in non-generic method

What I'm doing now:
void Main()
{
var command1 = new PersistenceCommand(new MyIntBO());
var command2 = new PersistenceCommand(new MyGuidBO());
var command3 = new PersistenceCommand(new PersistentBO());
Console.WriteLine(command1.ToString());
Console.WriteLine(command2.ToString());
Console.WriteLine(command3.ToString());
}
public class PersistenceCommand
{
public PersistenceCommand(PersistentBO businessObject)
{
_businessObject = businessObject;
}
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed<int>;
if (keyed != null)
{
result += " " + keyed.Id.ToString();
}
return result;
}
private readonly PersistentBO _businessObject;
}
public interface IPrimaryKeyed<out TKey>
{
TKey Id { get; }
}
public class PersistentBO {}
public class MyIntBO : PersistentBO, IPrimaryKeyed<int>
{
public int Id { get { return 1008; } }
}
public class MyGuidBO : PersistentBO, IPrimaryKeyed<Guid>
{
public Guid Id
{
get
{
return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29");
}
}
}
This prints:
MyIntBO 1008
MyGuidBO
PersistentBO
I'd like it to print:
MyIntBO 1008
MyGuidBO 6135d49b-81bb-43d4-9b74-dd84c2d3cc29
PersistentBO
What's the most elegant way to do that?
I want to support all types of keys - int, long, Guid, etc. - so I'd rather not do multiple casts. Note that not every business object implements that interface (some do not have a single primary key).
I realize I could use reflection and try to access the Id property. I was wondering if there's a better solution.
Clarification: To address #Acaz Souza and #Petar Ivanov's answers, we have dozens of classes scattered over multiple assemblies that already implement IPrimaryKeyed<T>. I do not want to break all of them by extending the interface contract. If I were designing this from scratch, their solutions would work.
Just create a non-generic interface and replace the generic one with generic abstract class. Then check for the interface:
public interface IPrimaryKeyed
{
object ObjId { get; }
}
public abstract class PrimaryKeyed<TKey> : IPrimaryKeyed
{
public object ObjId { get { return Id; } }
public abstract TKey Id { get; }
}
---
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed;
if (keyed != null)
{
result += " " + keyed.ObjId.ToString();
}
return result;
}
Using reflection doesn't seem like a bad way to go here.
ToString method:
// for getting the Id prop
var identProp = _businessObject.GetType().GetProperty("Id");
string result = _businessObject.GetType().Name;
if (identProp != null)
{
result += " " + identProp.GetValue(_businessObject, null).ToString();
}
The problem is in that line:
var keyed = _businessObject as IPrimaryKeyed<int>;
Your other type is not IPrimaryKeyed<int> is IPrimaryKeyed<Guid>, then the if (keyed != null) is false.
You can try do this:
static void Main()
{
var command1 = new PersistenceCommand(new MyIntBO());
var command2 = new PersistenceCommand(new MyGuidBO());
var command3 = new PersistenceCommand(new PersistentBO());
Console.WriteLine(command1.ToString());
Console.WriteLine(command2.ToString());
Console.WriteLine(command3.ToString());
Console.ReadLine();
}
public class PersistenceCommand
{
public PersistenceCommand(PersistentBO businessObject)
{
_businessObject = businessObject;
}
public override string ToString()
{
string result = _businessObject.GetType().Name;
var keyed = _businessObject as IPrimaryKeyed;
if (keyed != null)
{
result += " " + keyed.Id.ToString();
}
return result;
}
private readonly PersistentBO _businessObject;
}
public interface IPrimaryKeyed
{
object Id { get; }
}
public class PersistentBO { }
public class MyIntBO : PersistentBO, IPrimaryKeyed
{
public object Id { get { return 1008; } }
}
public class MyGuidBO : PersistentBO, IPrimaryKeyed
{
public object Id { get { return new Guid("6135d49b-81bb-43d4-9b74-dd84c2d3cc29"); } }
}

Categories

Resources