-4

How to declare and initialize below in a single line.

private Data model1 = new Data { M1 = 0, M2 = 0 };
private Data model2 = new Data { M1 = 0, M2 = 0 };
private Data model3 = new Data { M1 = 0, M2 = 0 };
private Data model4 = new Data { M1 = 0, M2 = 0 };
private Data model5 = new Data { M1 = 0, M2 = 0 };
....

Something like this →

private MyData model1, model2, model3, model4, model5 = new MyData {Max = 0, Min = 0};
st27
  • 9
  • 1
  • 6
  • 1
    So it throws the exception when you try to use the object? How do you use it? – maciek Jan 02 '23 at 13:53
  • 1
    are you sure that this line is throwing an error? – Vivek Nuna Jan 02 '23 at 13:55
  • 1
    Why do you need 5 distinct variable names instead of an array of 5 elements? With the later you can simply use a loop to initialize to the same value. – Steve Jan 02 '23 at 13:55
  • `int` fields and properties are initialized with `0` anyway. `private MyData model1 = new();` would do the same job. As other have said, use an array `private MyData[] models = { new(), new(), new(), new(), new() };` or a `List`. The lines you are showing most probably don't throw this exception. It must be somewhere else. – Olivier Jacot-Descombes Jan 02 '23 at 14:24
  • Does this answer your question? [What is a NullReferenceException, and how do I fix it?](https://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-and-how-do-i-fix-it) – Mark Benningfield Jan 02 '23 at 15:55
  • If you want to use an array then Brian's (or the other answers) work. If you want 5 unrelated instances then your first code block is the answer. The only single line solution is to remove all the carriage returns and put the five code blocks on one line! – MrC aka Shaun Curtis Jan 02 '23 at 17:53

3 Answers3

3

The "Object reference not set to an instance of an object" is a pretty famous error and has a canonical answer here. The error is not in the line where you try to initialize the model variables but in later use of the variables model1, model2, model3 and model4 only the last one model5 is created and initialized.

If you were happy with a collection, then there wouldn't be much of a problem. You could create an array for 5 MyData instances and loop over that array to initialize the 5 instances with the same values, but if you want to have 5 separate instances each assigned to 5 different variables names in a single line then, as far as I know, the feature doesn't exist and perhaps there is no real reason to have it. But I don't know if future releases of the language will allow it.

In the meantime there is a possible workaround albeit not the most clear solution. (Still, do you really need it?) It involves the use of a Tuple of 5 MyData

You can implement a static method inside the MyData class that return the 5 initialized variables like here

public class MyData
{ 
    public int Max { get; set; }
    public int Min { get; set; }
    
    public static (MyData model1, MyData model2, MyData model3,  
                   MyData model4, MyData model5)  
                   FiveInstanceFactory(int max, int min)
    {
        MyData[] factory = new MyData[5];
        for (int x = 0; x < factory.Length; x++)
            factory[x] = new MyData {Max = max,Min = min};
            
        return (factory[0], factory[1], factory[2], factory[3], factory[4]);
    }
}

Now you can have your one liner to create the 5 instances with the 5 names you like.

(MyData model1, MyData model2, MyData model3,  
 MyData model4, MyData model5) = MyData.FiveInstanceFactory(0,0);

model1.Max ++;
model2.Min++;

Console.WriteLine($"Min={model1.Min}, Max={model1.Max}");
Console.WriteLine($"Min={model2.Min}, Max={model2.Max}");
Steve
  • 213,761
  • 22
  • 232
  • 286
  • You are rite, only model5 is created and initialized – st27 Jan 02 '23 at 14:56
  • Your solution should suit me well. But says "MyData.FiveInstanceFactory(0,0) does not exist in current context". – st27 Jan 02 '23 at 15:52
  • Of course you need to add that method into the MyData class and if you are able to use an instance of MyData then you should be able to call that method. – Steve Jan 02 '23 at 16:13
  • I thought about it too. Earlier with the code in my question, I was able to access instance of MyData. Adding "MyData.FiveInstanceFactory(0,0) shows error as specified. I have the method included as well. Pls see under edited for reference. I notice that I am now not able to use min, max as well. – st27 Jan 02 '23 at 16:42
  • Sorry, but if that is the class MyData and it is in the same namespace of the code that uses it then there is no reason to have an error like that. What version of the NET or NET Framework are you using? Tuple is available only from NET Framework 4.7 onward. – Steve Jan 02 '23 at 16:48
  • Hi, my target framework is net5.0 – st27 Jan 02 '23 at 18:17
2
MyData[] data = Enumerable.Range(0, 5).Select(a => new MyData()).ToArray();
    public class MyData
    {
        public int Max { get; set; } = 0;
        public int Min { get; set; } = 0;
    }
Brian Parker
  • 11,946
  • 2
  • 31
  • 41
  • Tried applying this code, I get error as "does not contain definition for 'model1' or no accessible extension method 'model1 accepting a first argument..." on OpenDialog1. Similarly, for model2, model3... would you mind guiding me on how do I use 'data' in my code, so that these errors can be ignored. – st27 Jan 02 '23 at 15:10
  • @st27 Replace `modeli` by `data[i-1]`(ex: `model1` by `data[0]`). Similarly, you only need one OpenDialog, with the increment (or `MyData`) as an argument. – T.Trassoudaine Jan 02 '23 at 17:02
  • Thank you. Says cannot apply indexing with [] to an expression of type 'IEnumerable', when I try this.data[0] instead of this.model1. – st27 Jan 02 '23 at 18:34
1
 private var modelList = new List<MyData>();
 for(var i = 0; i < 5; i++)
     modelList.Add(new MyData { Max = 0, Min = 0});

It's not a single line but easier than what are you trying to do.

Alp
  • 358
  • 5
  • 12