Exception Handling: Object creation within try block
-
I'm currently getting into exception handling and have encountered the following problem. Let's say we have a class SampleClass. The SampleClass constructor takes various input parameters and is to check whether these are valid. If not exceptions might be thrown. Ideally I would like to have the code creating an object of type SampleClass to handle the potential exceptions. This does not quite work, as the compiler reports "Use of unassigned local variable..." outside the try block. Here's the code:
public class SampleClass { public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); // Compiler says: Use of unassigned local variable 's' } } }
I'd be quite pleased if someone could direct me into a promising direction. How to create object instances within try? You might say, just incorporate s.Action() within the try block. The problem is that in the real world example there is lots of code referencing 's'. So I'd end up with a massive try block and dozens of catch blocks afterwards. I reckon that's not what you would call best practices. Thanks in advance. All the best. Goebel -
I'm currently getting into exception handling and have encountered the following problem. Let's say we have a class SampleClass. The SampleClass constructor takes various input parameters and is to check whether these are valid. If not exceptions might be thrown. Ideally I would like to have the code creating an object of type SampleClass to handle the potential exceptions. This does not quite work, as the compiler reports "Use of unassigned local variable..." outside the try block. Here's the code:
public class SampleClass { public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); // Compiler says: Use of unassigned local variable 's' } } }
I'd be quite pleased if someone could direct me into a promising direction. How to create object instances within try? You might say, just incorporate s.Action() within the try block. The problem is that in the real world example there is lots of code referencing 's'. So I'd end up with a massive try block and dozens of catch blocks afterwards. I reckon that's not what you would call best practices. Thanks in advance. All the best. GoebelYou can't use s to do something outside the try/catch if the constructor fails. This is because the compiler can't guarantee that it is uninitialised. If your code is so interdependent then this suggests that you probably need to refactor the code where possible.
Deja View - the feeling that you've seen this post before.
-
I'm currently getting into exception handling and have encountered the following problem. Let's say we have a class SampleClass. The SampleClass constructor takes various input parameters and is to check whether these are valid. If not exceptions might be thrown. Ideally I would like to have the code creating an object of type SampleClass to handle the potential exceptions. This does not quite work, as the compiler reports "Use of unassigned local variable..." outside the try block. Here's the code:
public class SampleClass { public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); // Compiler says: Use of unassigned local variable 's' } } }
I'd be quite pleased if someone could direct me into a promising direction. How to create object instances within try? You might say, just incorporate s.Action() within the try block. The problem is that in the real world example there is lots of code referencing 's'. So I'd end up with a massive try block and dozens of catch blocks afterwards. I reckon that's not what you would call best practices. Thanks in advance. All the best. Goebelpublic class Tester
{
class Program
{
static void Main(string[] args)
{
SampleClass s = null;try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. **s = null;** } **if( s != null )** **{** s.Action(); // Compiler says: Use of unassigned local variable 's' **}** } }
}
This version should do the trick.
Regards, Tim
-
You can't use s to do something outside the try/catch if the constructor fails. This is because the compiler can't guarantee that it is uninitialised. If your code is so interdependent then this suggests that you probably need to refactor the code where possible.
Deja View - the feeling that you've seen this post before.
Pete O`Hanlon wrote:
If your code is so interdependent then this suggests that you probably need to refactor the code where possible
Thanks Pete, but I'm not sure how to apply the refactoring approach. The object instance of SampleClass will be passed to other objects yielding object composition. So quite a few lines of code depend on 's'. public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } A1Class a1 = new A1Class(s); A2Class a2 = new A2Class(s); //... AnClass an = new AnClass(s); } } }
-
Pete O`Hanlon wrote:
If your code is so interdependent then this suggests that you probably need to refactor the code where possible
Thanks Pete, but I'm not sure how to apply the refactoring approach. The object instance of SampleClass will be passed to other objects yielding object composition. So quite a few lines of code depend on 's'. public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } A1Class a1 = new A1Class(s); A2Class a2 = new A2Class(s); //... AnClass an = new AnClass(s); } } }
Is there some reason that your classes A1Class, etc..., aren't inside the try/catch block. I can see no reason why you couldn't do that.
Deja View - the feeling that you've seen this post before.
-
public class Tester
{
class Program
{
static void Main(string[] args)
{
SampleClass s = null;try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. **s = null;** } **if( s != null )** **{** s.Action(); // Compiler says: Use of unassigned local variable 's' **}** } }
}
This version should do the trick.
Regards, Tim
Thanks Tim. Your approach made me think of something else. So far there is no SampleClass default constructor. But I could provide one resulting in a valid object initialisation. In doing so we'd guarantee that there is an object of type SampleClass. Thereby I could avoid checking for null-reference whenever I use 's'. Is that too much of a workaround? public class SampleClass { public SampleClass() { this.param1 = 1; this.param2 = 1; } public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s = new SampleClass(); try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); } } } Thanks again, Goebel
-
Is there some reason that your classes A1Class, etc..., aren't inside the try/catch block. I can see no reason why you couldn't do that.
Deja View - the feeling that you've seen this post before.
Good point, Pete! I haven't thought of that as there is lots of preprocessing to do in order to setup classes A1Class, A2Class,... But I could easily do the preprocessing first and at a later stage initialise an object of SampleClass and create the various other objects within the try block. Thanks for helping me out. Goebel
-
Thanks Tim. Your approach made me think of something else. So far there is no SampleClass default constructor. But I could provide one resulting in a valid object initialisation. In doing so we'd guarantee that there is an object of type SampleClass. Thereby I could avoid checking for null-reference whenever I use 's'. Is that too much of a workaround? public class SampleClass { public SampleClass() { this.param1 = 1; this.param2 = 1; } public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s = new SampleClass(); try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); } } } Thanks again, Goebel
If you provide a default constructor, I would recommend not to use a second constructor for your purpose. Instead provide a method. Currently you assign a new object within the try/catch-block and I'm not sure what happens to
s
, if an exception is thrown within the second constructor.Goebel wrote:
public class SampleClass
{
public SampleClass()
{
this.param1 = 1;
this.param2 = 1;
}public **Assign**(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. }
}
public class Tester
{
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass();try { **s.Assign(20, 20);** } catch (Exception e) { // Do processing here. } s.Action(); } }
}
Regards, Tim
-
If you provide a default constructor, I would recommend not to use a second constructor for your purpose. Instead provide a method. Currently you assign a new object within the try/catch-block and I'm not sure what happens to
s
, if an exception is thrown within the second constructor.Goebel wrote:
public class SampleClass
{
public SampleClass()
{
this.param1 = 1;
this.param2 = 1;
}public **Assign**(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. }
}
public class Tester
{
class Program
{
static void Main(string[] args)
{
SampleClass s = new SampleClass();try { **s.Assign(20, 20);** } catch (Exception e) { // Do processing here. } s.Action(); } }
}
Regards, Tim
-
I'm currently getting into exception handling and have encountered the following problem. Let's say we have a class SampleClass. The SampleClass constructor takes various input parameters and is to check whether these are valid. If not exceptions might be thrown. Ideally I would like to have the code creating an object of type SampleClass to handle the potential exceptions. This does not quite work, as the compiler reports "Use of unassigned local variable..." outside the try block. Here's the code:
public class SampleClass { public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); // Compiler says: Use of unassigned local variable 's' } } }
I'd be quite pleased if someone could direct me into a promising direction. How to create object instances within try? You might say, just incorporate s.Action() within the try block. The problem is that in the real world example there is lots of code referencing 's'. So I'd end up with a massive try block and dozens of catch blocks afterwards. I reckon that's not what you would call best practices. Thanks in advance. All the best. Goebel -
I'm currently getting into exception handling and have encountered the following problem. Let's say we have a class SampleClass. The SampleClass constructor takes various input parameters and is to check whether these are valid. If not exceptions might be thrown. Ideally I would like to have the code creating an object of type SampleClass to handle the potential exceptions. This does not quite work, as the compiler reports "Use of unassigned local variable..." outside the try block. Here's the code:
public class SampleClass { public SampleClass(int param1, int param2) { int param1; int param2; if (param1 % param2 != 0) { throw new Exception(); } this.param1 = param1; this.param2 = param2; } public void Action() { // Some weird stuff in here. } } public class Tester { class Program { static void Main(string[] args) { SampleClass s; try { s = new SampleClass(20, 20); } catch (Exception e) { // Do processing here. } s.Action(); // Compiler says: Use of unassigned local variable 's' } } }
I'd be quite pleased if someone could direct me into a promising direction. How to create object instances within try? You might say, just incorporate s.Action() within the try block. The problem is that in the real world example there is lots of code referencing 's'. So I'd end up with a massive try block and dozens of catch blocks afterwards. I reckon that's not what you would call best practices. Thanks in advance. All the best. GoebelThe error you are getting is simply the compiler warning you that you are using a variable that may not be explicitly initialized during runtime depending which path the execution flow takes. In your case, you are using an uninitialised variable named s. The compiler is simply detecting that the execution might reach the catch and finally blocks with s never being explicitly initialized in your code and will therefore warn you because it's not sure if you know what you're doing (in your code this would happen if your class constructor throws an exception). On the other hand, if you explicitly initialize the variable s to null, which makes no difference at runtime to what you originally coded, the compiler understands that you know what you are doing and that you have factored in the possibility of s being null if the catch and finally blocks are ever executed. Please note that this is not something specific to try catch-blocks and constructors. You would get the same error in the following code (the code does not make much sense at all but its a valid example):
public void example(bool dummy) { myClass s; if (dummy) { s = new myClass(); } else { if (s==null) //do something else //do something else } }
Hope this clears it up a little for you. P.D. About the default constructor, C# does not work the same as C++. Having a default constructor will not make your variable s use it when its defined: myClass s; //this will not call the default constructor as in C++. C# initializes objects to null. Please note that the compiler error is not really necessary as the s variable is truely null even if not explicitly initialized and will therefore not cause unexpected behaviour reading uninitialised memory, etc. Its more an aid and a reminder to the coder that might be overlooking a possible execution path where the variable may not have the expected value. This becomes evident if instead of using your class you try your same code with int s; You will still get exactly the same error even though s is by default initialized to 0 and has a perfectly valid value. -- modified at 13:11 Monday 7th May, 2007