I have a class called "program" and a data dictionary called "mydic" in this class. Then I tried to write all data from "mydic" dictionary to a file name "expenses.txt". After that, I created another class called "Total_Expenses" that inherit from a "program" class. I tried to read all data from "expenses.txt" and then sorted it in descending order and write to a new file called "expenses_updated". Then I tried to calculate all expenses. But there is an error that stated that "The name "mydic" does not exist in this current context". I tried to create an object of "program" class and access "mydic" dictionary through this object and I also tried to access "mydic" dictionary through class (program.mydic), but none of these worked. Here are my codes:
"program" class:
using System;
using System.IO;
namespace Expense_File
{
public class program
{
public static void Main(String[] args)
{
Console.WriteLine("\n WritingtoFile");
WritingtoFile("d:/expenses.txt");
string filename = Console.ReadLine();
WritingtoFile(filename);
Console.Write("Press any to continue...");
Console.ReadKey();
}
public static void WritingtoFile(string filename)
{
FileStream fs = null;
try
{
fs = new FileStream(filename, FileMode.CreateNew);
}
catch (Exception ex)
{
Console.WriteLine($"Creating new file: {ex.Message}");
return;
}
StreamWriter sw = new StreamWriter(fs);
Dictionary<string, int> mydic = new Dictionary<string, int>()
{
{"Studying",200},
{"Food",500},
{"Picnic",300},
{"Community",50},
{"Others",150}
};
foreach (KeyValuePair<string, int> ele in mydic)
{
sw.WriteLine("{0}: {1}", ele.Key, ele.Value);
}
sw.Close();
Console.WriteLine($"Successfully created new file, {filename}");
}
}
}
"Total_Expenses" class:
using System;
using System.IO;
namespace Expense_File
{
class Total_Expenses:program
{
public static void Main(String[] args)
{
Console.WriteLine("\n WritingtoFile");
WritetoFile("d:/expenses_updated.txt");
string filename = Console.ReadLine();
WritetoFile(filename);
Console.Write("Press any to continue...");
Console.ReadKey();
}
static void WritetoFile(string filename)
{
FileStream fs = null;
try
{
fs = new FileStream(filename, FileMode.CreateNew);
}
catch (Exception ex)
{
Console.WriteLine($"Creating new file: {ex.Message}");
return;
}
StreamWriter sw = new StreamWriter(fs);
var mydic_descen = from ele in mydic
orderby ele.Value descending
select ele;
foreach (KeyValuePair<string, int> ele in mydic_descen)
{
sw.WriteLine("{0}: {1}", ele.Key, ele.Value);
}
int sum = 0;
foreach (KeyValuePair<string, int> ele in mydic_descen)
{
sum = sum ele.Value;
}
sw.WriteLine("--------------");
sw.WriteLine("Total:" sum);
sw.Close();
Console.WriteLine($"Successfully created new file, {filename}");
}
}
}
CodePudding user response:
While you have classes, all your method is static. Static methods are great when you want to take some input and produce some output, but they are limited in that they cannot use instance variables (i.e. fields) and does not interact at all with inheritance.
You probably want a class that encapsulates your data, something like
public class MyData{
private Dictionary<string, int> Mydictionary {get;}
public MyData(Dictionary<string, int> myDictionary) => Mydictionary = myDictionary;
public WritingtoFile(){
...
}
And instantiate this in your Main-method:
public static void Main(String[] args)
{
var data = new MyData(...);
data.WriteToFile(...);
}
I would highly encourage your to study a bit more about object oriented design, since this is a rather fundamental concept. But I would recommend to avoid inheritance as much as possible, while this has its place, there is a tendency for newer programmers to go overboard with it. I would also suggest using a serialization library rather then writing and reading files by hand, this will likely be both simpler and more flexible. See Json.Net for an example.
CodePudding user response:
In my view, inheritance is not good choice for code of writing file. Why? Because we do not want to change behavior of writing file, we always want to write file.
In addition, method WritetoFile()
has many responsibilities such as:
- collecting ydic_descen
- ordering this collection
- writing different strings such as
sw.WriteLine("Total:" sum);
What we can do? We can extract duplicate code of writing file to a class. By doing this, we uses SingleResponsibility Principle of SOLID. Does the Single Responsibility Principle work in OOP?
public class FileManager
{
public void WriteTo(string fileName, IEnumerable<string> rows)
{
using FileStream fs = new FileStream(fileName, FileMode.CreateNew);
using StreamWriter sw = new StreamWriter(fs);
foreach (string row in rows)
sw.WriteLine(row);
}
public IEnumerable<string> ReadFrom(string fileName)
{
return File.ReadLines(fileName);
}
}
and then there are classes where we can use inheritance because we want to redefine behaviour for classes. So we can create abstract class which defines behavior for derived classes:
public abstract class SomeText
{
public Dictionary<string, int> MyDictionary { get; private set; }
public SomeText(Dictionary<string, int> myDictionary)
{
MyDictionary = myDictionary;
}
public abstract IEnumerable<string> Get();
}
and its concrete implementations:
public class ExpenseText : SomeText
{
public ExpenseText(Dictionary<string, int> myDictionary) : base(myDictionary)
{
}
public override IEnumerable<string> Get()
{
List<string> rows = new List<string>();
foreach (KeyValuePair<string, int> ele in MyDictionary)
{
rows.Add($"{ele.Key}: {ele.Value}");
}
return rows;
}
}
Total_Expenses_Text
class:
public class Total_Expenses_Text : SomeText
{
public Total_Expenses_Text(Dictionary<string, int> myDictionary) : base(myDictionary)
{
}
public override IEnumerable<string> Get()
{
List<string> rows = new List<string>();
IOrderedEnumerable<KeyValuePair<string, int>> descendanKeyValuePairs =
MyDictionary.OrderByDescending(s => s.Value);
foreach (KeyValuePair<string, int> ele in descendanKeyValuePairs)
{
rows.Add($"{ele.Key}: {ele.Value}");
}
int sum = 0;
foreach (KeyValuePair<string, int> ele in descendanKeyValuePairs)
{
sum = sum ele.Value;
}
rows.Add("--------------");
rows.Add("Total:" sum);
return rows;
}
}
and service which orchestrates by these classes:
public class FileService
{
public void WriteToFile(string fileName, SomeText someText)
{
IEnumerable<string> rows = someText.Get();
FileManager fileManager = new FileManager();
fileManager.WriteTo(fileName, rows);
}
}
And you can call FileService like this:
class Program
{
static void Main(string[] args)
{
Dictionary<string, int> mydic = new Dictionary<string, int>()
{
{"Studying",200},
{"Food",500},
{"Picnic",300},
{"Community",50},
{"Others",150}
};
new FileService().WriteToFile("D:/fooBar.txt", new Total_Expenses_Text(mydic));
}
}
So we've created simple classes that are testable.