0

I've created a WindowsForm Application with 3 buttons. A click on any of the buttons reads c:\data.txt and performs a different "analysis" of the data. Button 1 might add the numbers in data.txt, Button 2 might average them, and Button 3 might multiply them.

Under each private void button1_Click I have a line of code that reads in the data from data.txt. This seems inefficient to me since the same "ReadLines" code is in each of the 3 button click events.

Is there a way to read the data just ONCE, and then have my buttons perform their analysis?

This way, the "ReadLines" code is only used once, and the data is somehow shared with any of the button1_Click events.

Oded
  • 489,969
  • 99
  • 883
  • 1,009
MrPatterns
  • 4,184
  • 27
  • 65
  • 85

4 Answers4

5

This is not difficult - you need to have a field to hold the values you read - the field will be available to all of your functions in the class.

 private string[] data;

 // in constructor:
 data = File.ReadAllLines(@"c:\data.txt");

 // in your methods, simply use data

Another option is to have a LoadData method that checks if data is null or not and call it from your methods:

private void LoadData()
{
  if(data == null)
    data = File.ReadAllLines(@"c:\data.txt");
}
Oded
  • 489,969
  • 99
  • 883
  • 1,009
2

If you want to further maximise the efficiency you could use a field and a property to lazy load it.

private string[] _data;

private string[] Data
{
    get
    {
        return _data ?? _data = File.ReadAllLines(@"c:\data.txt");
    }
}

Now your calling code can just consume the property without having to check if the field is null and you don't load the data until you need it.

RobH
  • 3,604
  • 1
  • 23
  • 46
  • 2
    I like the use of the null coalesce, it's an underused operator. However, not a fan of assignment and return on the same line... – CaffGeek Sep 12 '12 at 15:37
  • I guess it's preference but I like the compact code. I know some people don't like it but I prefer it to the check for null, then assign and then return. It's so long winded! I find this approach less cumbersome. – RobH Sep 12 '12 at 15:43
  • I am also not a fan of properties doing work like reading from disk. – Oded Sep 12 '12 at 15:43
  • 1
    @Oded - that's a fair comment. I assumed given the button1_Click in the question that this isn't production code. – RobH Sep 12 '12 at 15:45
  • You should see the production code I am working on. Full of these :( – Oded Sep 12 '12 at 16:09
1

To your class add property that will perform lazy loading.

First add a place to store the data

private string[] _FileData;

Then add a new property

private string[] FileData 
{ 
    get
    {
        if (_FileData != null && _FileData.Length > 0)
            return _FileData;

        _FileData = File.ReadAllLines(@"c:\data.txt");

        return _FileData;
    }
}

Then just use the FileData property to get the file text. It will only get the file text the first time, after that, _FileData will hold your file, and it will just get returned when you access FileData.

CaffGeek
  • 21,856
  • 17
  • 100
  • 184
1

Here's an equally generic answer ;)

You can declare a shared variable (e.g. a string) which, on each button click handler, you check to see is empty or null (String.IsNullOrEmpty(myString)). If it's empty, perform the ReadLines code and store the data in your string variable. Then do the processing on the variable.

The next time you click a button, you will see that your string is not empty, and just process the string, instead of having to read the file again.

theyetiman
  • 8,514
  • 2
  • 32
  • 41