String value not getting modified in a recursion - c#

I am trying to modify a string inside a recursion . Here is the code :-
using System;
public class Program
{
public static void Main()
{
string s = "abcdc";
string added = "";
checkIfPalindrome(s , added);
Console.WriteLine( added);
}
public static void checkIfPalindrome(string s , string added)
{
//Console.WriteLine(added);
if(s.Length < 2)
{
return;
}
if(s[0] == s[s.Length -1])
{
checkIfPalindrome(s.Substring(1,s.Length-2) , added);
}
else
{
added = s[0] + added;
checkIfPalindrome(s.Substring(1,s.Length-1), added) ;
}
}
}
Here is the fiddle for the same :-
<iframe width="100%" height="475" src="https://dotnetfiddle.net/Widget/u4119h" frameborder="0"></iframe>
I am expecting added to be modified inside recursion and appear as a result outside function call and inside main method, since string is a reference type .But the value of added literal is an empty string . Although when recursion hits the base case , it has ba as value.
Also correct value is reflected when ref keyword is used for passing added
Is my understanding wrong ?

At the very top, you're assigning a value to the added local in your Main function. But you're never changing that value. You're only ever changing what the argument of checkIfPalindrome points to. This has no effect on the local added in Main, unless you pass it by reference - using ref.
Reference types have reference semantics, yes. But that doesn't mean that a reference to a reference type has the same property. If you modified the value of added, you would get the behaviour you expect - but you only ever replace the argument's reference - pointing it somewhere else. Of course, strings in .NET are immutable, so you can't actually change the value of added - your only option is to pass the string by reference (or better, make it a return value, which makes for much clearer recursion anyway).

string is a reference type but immutable which means it cannot be changed after it has been created. Every change to a string will create a new string.

Related

why pass string doesn't work even string is passed as reference in function? [duplicate]

I know that "string" in C# is a reference type. This is on MSDN. However, this code doesn't work as it should then:
class Test
{
public static void Main()
{
string test = "before passing";
Console.WriteLine(test);
TestI(test);
Console.WriteLine(test);
}
public static void TestI(string test)
{
test = "after passing";
}
}
The output should be "before passing" "after passing" since I'm passing the string as a parameter and it being a reference type, the second output statement should recognize that the text changed in the TestI method. However, I get "before passing" "before passing" making it seem that it is passed by value not by ref. I understand that strings are immutable, but I don't see how that would explain what is going on here. What am I missing? Thanks.
The reference to the string is passed by value. There's a big difference between passing a reference by value and passing an object by reference. It's unfortunate that the word "reference" is used in both cases.
If you do pass the string reference by reference, it will work as you expect:
using System;
class Test
{
public static void Main()
{
string test = "before passing";
Console.WriteLine(test);
TestI(ref test);
Console.WriteLine(test);
}
public static void TestI(ref string test)
{
test = "after passing";
}
}
Now you need to distinguish between making changes to the object which a reference refers to, and making a change to a variable (such as a parameter) to let it refer to a different object. We can't make changes to a string because strings are immutable, but we can demonstrate it with a StringBuilder instead:
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder test = new StringBuilder();
Console.WriteLine(test);
TestI(test);
Console.WriteLine(test);
}
public static void TestI(StringBuilder test)
{
// Note that we're not changing the value
// of the "test" parameter - we're changing
// the data in the object it's referring to
test.Append("changing");
}
}
See my article on parameter passing for more details.
If we have to answer the question: String is a reference type and it behaves as a reference. We pass a parameter that holds a reference to, not the actual string. The problem is in the function:
public static void TestI(string test)
{
test = "after passing";
}
The parameter test holds a reference to the string but it is a copy. We have two variables pointing to the string. And because any operations with strings actually create a new object, we make our local copy to point to the new string. But the original test variable is not changed.
The suggested solutions to put ref in the function declaration and in the invocation work because we will not pass the value of the test variable but will pass just a reference to it. Thus any changes inside the function will reflect the original variable.
I want to repeat at the end: String is a reference type but since its immutable the line test = "after passing"; actually creates a new object and our copy of the variable test is changed to point to the new string.
As others have stated, the String type in .NET is immutable and it's reference is passed by value.
In the original code, as soon as this line executes:
test = "after passing";
then test is no longer referring to the original object. We've created a new String object and assigned test to reference that object on the managed heap.
I feel that many people get tripped up here since there's no visible formal constructor to remind them. In this case, it's happening behind the scenes since the String type has language support in how it is constructed.
Hence, this is why the change to test is not visible outside the scope of the TestI(string) method - we've passed the reference by value and now that value has changed! But if the String reference were passed by reference, then when the reference changed we will see it outside the scope of the TestI(string) method.
Either the ref or out keyword are needed in this case. I feel the out keyword might be slightly better suited for this particular situation.
class Program
{
static void Main(string[] args)
{
string test = "before passing";
Console.WriteLine(test);
TestI(out test);
Console.WriteLine(test);
Console.ReadLine();
}
public static void TestI(out string test)
{
test = "after passing";
}
}
"A picture is worth a thousand words".
I have a simple example here, it's similar to your case.
string s1 = "abc";
string s2 = s1;
s1 = "def";
Console.WriteLine(s2);
// Output: abc
This is what happened:
Line 1 and 2: s1 and s2 variables reference to the same "abc" string object.
Line 3: Because strings are immutable, so the "abc" string object does not modify itself (to "def"), but a new "def" string object is created instead, and then s1 references to it.
Line 4: s2 still references to "abc" string object, so that's the output.
Actually it would have been the same for any object for that matter i.e. being a reference type and passing by reference are 2 different things in c#.
This would work, but that applies regardless of the type:
public static void TestI(ref string test)
Also about string being a reference type, its also a special one. Its designed to be immutable, so all of its methods won't modify the instance (they return a new one). It also has some extra things in it for performance.
Here's a good way to think about the difference between value-types, passing-by-value, reference-types, and passing-by-reference:
A variable is a container.
A value-type variable contains an instance.
A reference-type variable contains a pointer to an instance stored elsewhere.
Modifying a value-type variable mutates the instance that it contains.
Modifying a reference-type variable mutates the instance that it points to.
Separate reference-type variables can point to the same instance.
Therefore, the same instance can be mutated via any variable that points to it.
A passed-by-value argument is a new container with a new copy of the content.
A passed-by-reference argument is the original container with its original content.
When a value-type argument is passed-by-value:
Reassigning the argument's content has no effect outside scope, because the container is unique.
Modifying the argument has no effect outside scope, because the instance is an independent copy.
When a reference-type argument is passed-by-value:
Reassigning the argument's content has no effect outside scope, because the container is unique.
Modifying the argument's content affects the external scope, because the copied pointer points to a shared instance.
When any argument is passed-by-reference:
Reassigning the argument's content affects the external scope, because the container is shared.
Modifying the argument's content affects the external scope, because the content is shared.
In conclusion:
A string variable is a reference-type variable. Therefore, it contains a pointer to an instance stored elsewhere.
When passed-by-value, its pointer is copied, so modifying a string argument should affect the shared instance.
However, a string instance has no mutable properties, so a string argument cannot be modified anyway.
When passed-by-reference, the pointer's container is shared, so reassignment will still affect the external scope.
Above answers are helpful, I'd just like to add an example that I think is demonstrating clearly what happens when we pass parameter without the ref keyword, even when that parameter is a reference type:
MyClass c = new MyClass(); c.MyProperty = "foo";
CNull(c); // only a copy of the reference is sent
Console.WriteLine(c.MyProperty); // still foo, we only made the copy null
CPropertyChange(c);
Console.WriteLine(c.MyProperty); // bar
private void CNull(MyClass c2)
{
c2 = null;
}
private void CPropertyChange(MyClass c2)
{
c2.MyProperty = "bar"; // c2 is a copy, but it refers to the same object that c does (on heap) and modified property would appear on c.MyProperty as well.
}
For curious minds and to complete the conversation:
Yes, String is a reference type:
unsafe
{
string a = "Test";
string b = a;
fixed (char* p = a)
{
p[0] = 'B';
}
Console.WriteLine(a); // output: "Best"
Console.WriteLine(b); // output: "Best"
}
But note that this change only works in an unsafe block! because Strings are immutable (From MSDN):
The contents of a string object cannot be changed after the object is
created, although the syntax makes it appear as if you can do this.
For example, when you write this code, the compiler actually creates a
new string object to hold the new sequence of characters, and that new
object is assigned to b. The string "h" is then eligible for garbage
collection.
string b = "h";
b += "ello";
And keep in mind that:
Although the string is a reference type, the equality operators (== and
!=) are defined to compare the values of string objects, not
references.
Try:
public static void TestI(ref string test)
{
test = "after passing";
}
I believe your code is analogous to the following, and you should not have expected the value to have changed for the same reason it wouldn't here:
public static void Main()
{
StringWrapper testVariable = new StringWrapper("before passing");
Console.WriteLine(testVariable);
TestI(testVariable);
Console.WriteLine(testVariable);
}
public static void TestI(StringWrapper testParameter)
{
testParameter = new StringWrapper("after passing");
// this will change the object that testParameter is pointing/referring
// to but it doesn't change testVariable unless you use a reference
// parameter as indicated in other answers
}
Another way to bypass the string behavior. Use string array of ONE element only and manipulate this element.
class Test
{
public static void Main()
{
string[] test = new string[1] {"before passing"};
Console.WriteLine(ref test);
TestI(test);
Console.WriteLine(ref test);
}
public static void TestI(ref string[] test)
{
test[0] = "after passing";
}
}

I can't add to a value when i use parameter, but it works fine when not in the function

So when i try to += 1 in the function, the value doesent update, But i can update the value without paramter just fine.
Please help.
public void buystock(int amountofstocks, int stockvalue)
{
int stocksbuy = 400;
if (amountofstocks >= 40)
{
if (GetComponent<Money>().MoneyValue >= (stockvalue + stocksbuy))
{
GetComponent<Money>().MoneyValue -= stockvalue + 400;
amountofstocks += 1;
}
}
else
{
if (GetComponent<Money>().MoneyValue >= (stockvalue + 10))
{
GetComponent<Money>().MoneyValue -= stockvalue + 10;
}
}
}
and my other one which is:
public void buyoil1()
{
buystock(oil1amountofstocks, oil1value);
}
Thanks a lot!
Int is value type, so it's value is copied (opposite to it's reference) into function parameter and any modification on that parameter is local.
In order to pass reference of int, you should use ref keyword.
Try following
public void buystock(ref int amountofstocks,ref int stockvalue)
You are passing a struct to your method which is copying the value rather than passing a reference to the variable.
Consider using a return value, out or ref to achieve the desired result.
Here is the official documentation on passing arguments to methods in C# which helps explain the problem
Its amazing how many answers here are simply wrong. They all go on about int being a value type and that bit of information is completely irrelevant here.
int is an immutable type, you can’t mutate it which would be the only reason why value types could be relevant in the context of this question.
Somehow the answers seem to be mixing up amountofstocks =+ 1 with mutating a value type which is simply false! The only thing that is going on here is that the variable amountofstock is being assigned a new value and because the parameter is passed by value (default behavior in c#) the assignment has no effect whatsoever back at the call site (the assignment is made on a copy).
The exact same thing would happen if amountofstock were a reference type. If amountofstring were to be a string there would be no change at all in the behavior of your code.
To make a long story short, the behavior you are seeing is due to the fact that parameters in c# are, by default, passed by value, period. It has nothing to do, in this particular case, with amountofstock being a value type.
If you need to reassign the value of a parameter and have it persist back at the call site then you need to pass it by reference; in your case ref amountofstock although in some scenarios out is more appropriate.

How does reference parameter work in a function [duplicate]

I know that "string" in C# is a reference type. This is on MSDN. However, this code doesn't work as it should then:
class Test
{
public static void Main()
{
string test = "before passing";
Console.WriteLine(test);
TestI(test);
Console.WriteLine(test);
}
public static void TestI(string test)
{
test = "after passing";
}
}
The output should be "before passing" "after passing" since I'm passing the string as a parameter and it being a reference type, the second output statement should recognize that the text changed in the TestI method. However, I get "before passing" "before passing" making it seem that it is passed by value not by ref. I understand that strings are immutable, but I don't see how that would explain what is going on here. What am I missing? Thanks.
The reference to the string is passed by value. There's a big difference between passing a reference by value and passing an object by reference. It's unfortunate that the word "reference" is used in both cases.
If you do pass the string reference by reference, it will work as you expect:
using System;
class Test
{
public static void Main()
{
string test = "before passing";
Console.WriteLine(test);
TestI(ref test);
Console.WriteLine(test);
}
public static void TestI(ref string test)
{
test = "after passing";
}
}
Now you need to distinguish between making changes to the object which a reference refers to, and making a change to a variable (such as a parameter) to let it refer to a different object. We can't make changes to a string because strings are immutable, but we can demonstrate it with a StringBuilder instead:
using System;
using System.Text;
class Test
{
public static void Main()
{
StringBuilder test = new StringBuilder();
Console.WriteLine(test);
TestI(test);
Console.WriteLine(test);
}
public static void TestI(StringBuilder test)
{
// Note that we're not changing the value
// of the "test" parameter - we're changing
// the data in the object it's referring to
test.Append("changing");
}
}
See my article on parameter passing for more details.
If we have to answer the question: String is a reference type and it behaves as a reference. We pass a parameter that holds a reference to, not the actual string. The problem is in the function:
public static void TestI(string test)
{
test = "after passing";
}
The parameter test holds a reference to the string but it is a copy. We have two variables pointing to the string. And because any operations with strings actually create a new object, we make our local copy to point to the new string. But the original test variable is not changed.
The suggested solutions to put ref in the function declaration and in the invocation work because we will not pass the value of the test variable but will pass just a reference to it. Thus any changes inside the function will reflect the original variable.
I want to repeat at the end: String is a reference type but since its immutable the line test = "after passing"; actually creates a new object and our copy of the variable test is changed to point to the new string.
As others have stated, the String type in .NET is immutable and it's reference is passed by value.
In the original code, as soon as this line executes:
test = "after passing";
then test is no longer referring to the original object. We've created a new String object and assigned test to reference that object on the managed heap.
I feel that many people get tripped up here since there's no visible formal constructor to remind them. In this case, it's happening behind the scenes since the String type has language support in how it is constructed.
Hence, this is why the change to test is not visible outside the scope of the TestI(string) method - we've passed the reference by value and now that value has changed! But if the String reference were passed by reference, then when the reference changed we will see it outside the scope of the TestI(string) method.
Either the ref or out keyword are needed in this case. I feel the out keyword might be slightly better suited for this particular situation.
class Program
{
static void Main(string[] args)
{
string test = "before passing";
Console.WriteLine(test);
TestI(out test);
Console.WriteLine(test);
Console.ReadLine();
}
public static void TestI(out string test)
{
test = "after passing";
}
}
"A picture is worth a thousand words".
I have a simple example here, it's similar to your case.
string s1 = "abc";
string s2 = s1;
s1 = "def";
Console.WriteLine(s2);
// Output: abc
This is what happened:
Line 1 and 2: s1 and s2 variables reference to the same "abc" string object.
Line 3: Because strings are immutable, so the "abc" string object does not modify itself (to "def"), but a new "def" string object is created instead, and then s1 references to it.
Line 4: s2 still references to "abc" string object, so that's the output.
Actually it would have been the same for any object for that matter i.e. being a reference type and passing by reference are 2 different things in c#.
This would work, but that applies regardless of the type:
public static void TestI(ref string test)
Also about string being a reference type, its also a special one. Its designed to be immutable, so all of its methods won't modify the instance (they return a new one). It also has some extra things in it for performance.
Here's a good way to think about the difference between value-types, passing-by-value, reference-types, and passing-by-reference:
A variable is a container.
A value-type variable contains an instance.
A reference-type variable contains a pointer to an instance stored elsewhere.
Modifying a value-type variable mutates the instance that it contains.
Modifying a reference-type variable mutates the instance that it points to.
Separate reference-type variables can point to the same instance.
Therefore, the same instance can be mutated via any variable that points to it.
A passed-by-value argument is a new container with a new copy of the content.
A passed-by-reference argument is the original container with its original content.
When a value-type argument is passed-by-value:
Reassigning the argument's content has no effect outside scope, because the container is unique.
Modifying the argument has no effect outside scope, because the instance is an independent copy.
When a reference-type argument is passed-by-value:
Reassigning the argument's content has no effect outside scope, because the container is unique.
Modifying the argument's content affects the external scope, because the copied pointer points to a shared instance.
When any argument is passed-by-reference:
Reassigning the argument's content affects the external scope, because the container is shared.
Modifying the argument's content affects the external scope, because the content is shared.
In conclusion:
A string variable is a reference-type variable. Therefore, it contains a pointer to an instance stored elsewhere.
When passed-by-value, its pointer is copied, so modifying a string argument should affect the shared instance.
However, a string instance has no mutable properties, so a string argument cannot be modified anyway.
When passed-by-reference, the pointer's container is shared, so reassignment will still affect the external scope.
Above answers are helpful, I'd just like to add an example that I think is demonstrating clearly what happens when we pass parameter without the ref keyword, even when that parameter is a reference type:
MyClass c = new MyClass(); c.MyProperty = "foo";
CNull(c); // only a copy of the reference is sent
Console.WriteLine(c.MyProperty); // still foo, we only made the copy null
CPropertyChange(c);
Console.WriteLine(c.MyProperty); // bar
private void CNull(MyClass c2)
{
c2 = null;
}
private void CPropertyChange(MyClass c2)
{
c2.MyProperty = "bar"; // c2 is a copy, but it refers to the same object that c does (on heap) and modified property would appear on c.MyProperty as well.
}
For curious minds and to complete the conversation:
Yes, String is a reference type:
unsafe
{
string a = "Test";
string b = a;
fixed (char* p = a)
{
p[0] = 'B';
}
Console.WriteLine(a); // output: "Best"
Console.WriteLine(b); // output: "Best"
}
But note that this change only works in an unsafe block! because Strings are immutable (From MSDN):
The contents of a string object cannot be changed after the object is
created, although the syntax makes it appear as if you can do this.
For example, when you write this code, the compiler actually creates a
new string object to hold the new sequence of characters, and that new
object is assigned to b. The string "h" is then eligible for garbage
collection.
string b = "h";
b += "ello";
And keep in mind that:
Although the string is a reference type, the equality operators (== and
!=) are defined to compare the values of string objects, not
references.
Try:
public static void TestI(ref string test)
{
test = "after passing";
}
I believe your code is analogous to the following, and you should not have expected the value to have changed for the same reason it wouldn't here:
public static void Main()
{
StringWrapper testVariable = new StringWrapper("before passing");
Console.WriteLine(testVariable);
TestI(testVariable);
Console.WriteLine(testVariable);
}
public static void TestI(StringWrapper testParameter)
{
testParameter = new StringWrapper("after passing");
// this will change the object that testParameter is pointing/referring
// to but it doesn't change testVariable unless you use a reference
// parameter as indicated in other answers
}
Another way to bypass the string behavior. Use string array of ONE element only and manipulate this element.
class Test
{
public static void Main()
{
string[] test = new string[1] {"before passing"};
Console.WriteLine(ref test);
TestI(test);
Console.WriteLine(ref test);
}
public static void TestI(ref string[] test)
{
test[0] = "after passing";
}
}

how a method with string as its parameter in C#

This below code compiles and works out as intended.
class MyClass1
{
public void test()
{
string one = "testString1";
Console.WriteLine("MyClass1: " + one);
new MyClass2().test(one);
Console.WriteLine(one); //again testString1 is printed.
}
}
class MyClass2
{
public void test(string two)
{
Console.WriteLine("Test method");
Console.WriteLine(two);
two = "pilot";
Console.WriteLine(two);
}
}
all I infer from this is:
The value assigned to the string in test method is local to that function and the changes will be reflected only if I use a ref or out.
The question is:
We all know that the string is a reference type (because it is of type, String)
So, for all the reference types : when passing around their objects, the changes should be reflected right ? (For ex, for the same example, if I pass around a object of a class, then any changes are reflected back right ?)
Why is this rule not followed here ?
Can any one point me in understanding what happens under the hood ?
Although strings are reference objects, they are also immutable. Since references are passed by value *, changes to variables representing the reference, are not reflected on the original.
To demonstrate the effect of passing reference objects, replace string with StringBuilder, and change the content inside the test method:
class MyClass1
{
public void test()
{
StringBuilder one = new StringBuilder("testString1");
Console.WriteLine("MyClass1: " + one);
new MyClass2().test(one);
Console.WriteLine(one); //testString1pilot is printed.
}
}
class MyClass2
{
public void test(StringBuilder two)
{
Console.WriteLine("Test method");
Console.WriteLine(two);
two.Append("pilot");
Console.WriteLine(two);
}
}
* Unless the method specifies a different mode of parameter passing, e.g. out or ref.
So, for all the reference types : when passing around their objects,
the changes should be reflected right ?
All reference types are passed by reference is not true.
all reference type or value types are passed by value by default.
if you want to pass any type as reference types you need to use ref or out keyword.
Note: String is a immutable type means Strings can not be changed.
That is the reason why you are not able to see the changes made in the called function.
You need to use StringBuilder to get back the changes.
JonSteek has explained about Parmeter passing well here
In your example, the fact that String is a reference type does not matter. The exact same thing would happen with any value type or even a mutable reference type (like a class).
This is because the parameter to a method normally acts like a local variable within the method. Changes made to the parameter are local to the method.
As you stated, the exception is when the parameter is ref or out.
You have to understand the difference between the string which is a reference type and the variable itself that points to that object.
two = "pilot";
When you do this, you are creating a new string object and telling variable two to now point to this new string. The variable one still points to the original string, which is a different object.

A property or indexer may not be passed as an out or ref parameter

I'm getting the above error and unable to resolve it.
I googled a bit but can't get rid of it.
Scenario:
I have class BudgetAllocate whose property is budget which is of double type.
In my dataAccessLayer,
In one of my classes I am trying to do this:
double.TryParse(objReader[i].ToString(), out bd.Budget);
Which is throwing this error:
Property or indexer may not be passed as an out or ref parameter at
compile time.
I even tried this:
double.TryParse(objReader[i].ToString().Equals(DBNull.Value) ? "" : objReader[i].ToString(), out bd.Budget);
Everything else is working fine and references between layers are present.
Others have given you the solution, but as to why this is necessary: a property is just syntactic sugar for a method.
For example, when you declare a property called Name with a getter and setter, under the hood the compiler actually generates methods called get_Name() and set_Name(value). Then, when you read from and write to this property, the compiler translates these operations into calls to those generated methods.
When you consider this, it becomes obvious why you can't pass a property as an output parameter - you would actually be passing a reference to a method, rather than a reference to an object a variable, which is what an output parameter expects.
A similar case exists for indexers.
This is a case of a leaky abstraction. A property is actually a method, the get and set accessors for an indexer get compiled to get_Index() and set_Index methods. The compiler does a terrific job hiding that fact, it automatically translates an assignment to a property to the corresponding set_Xxx() method for example.
But this goes belly up when you pass a method parameter by reference. That requires the JIT compiler to pass a pointer to the memory location of the passed argument. Problem is, there isn't one, assigning the value of a property requires calling the setter method. The called method cannot tell the difference between a passed variable vs a passed property and can thus not know whether a method call is required.
Notable is that this actually works in VB.NET. For example:
Class Example
Public Property Prop As Integer
Public Sub Test(ByRef arg As Integer)
arg = 42
End Sub
Public Sub Run()
Test(Prop) '' No problem
End Sub
End Class
The VB.NET compiler solves this by automatically generating this code for the Run method, expressed in C#:
int temp = Prop;
Test(ref temp);
Prop = temp;
Which is the workaround you can use as well. Not quite sure why the C# team didn't use the same approach. Possibly because they didn't want to hide the potentially expensive getter and setter calls. Or the completely undiagnosable behavior you'll get when the setter has side-effects that change the property value, they'll disappear after the assignment. Classic difference between C# and VB.NET, C# is "no surprises", VB.NET is "make it work if you can".
you cannot use
double.TryParse(objReader[i].ToString(), out bd.Budget);
replace bd.Budget with some variable.
double k;
double.TryParse(objReader[i].ToString(), out k);
Possibly of interest - you could write your own:
//double.TryParse(, out bd.Budget);
bool result = TryParse(s, value => bd.Budget = value);
}
public bool TryParse(string s, Action<double> setValue)
{
double value;
var result = double.TryParse(s, out value);
if (result) setValue(value);
return result;
}
Place the out parameter into a local variable and then set the variable into bd.Budget:
double tempVar = 0.0;
if (double.TryParse(objReader[i].ToString(), out tempVar))
{
bd.Budget = tempVar;
}
Update: Straight from MSDN:
Properties are not variables and
therefore cannot be passed as out
parameters.
This is a very old post, but I'm ammending the accepted, because there is an even more convienient way of doing this which I didn't know.
It's called inline declaration and might have always been available (as in using statements) or it might have been added with C#6.0 or C#7.0 for such cases, not sure, but works like a charm anyway:
Inetad of this
double temp;
double.TryParse(objReader[i].ToString(), out temp);
bd.Budget = temp;
use this:
double.TryParse(objReader[i].ToString(), out double temp);
bd.Budget = temp;
So Budget is a property, correct?
Rather first set it to a local variable, and then set the property value to that.
double t = 0;
double.TryParse(objReader[i].ToString(), out t);
bd.Budget = t;
Usually when I'm trying to do this it's because I want to set my property or leave it at the default value. With the help of this answer and dynamic types we can easily create a string extension method to keep it one lined and simple.
public static dynamic ParseAny(this string text, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
if (converter != null && converter.IsValid(text))
return converter.ConvertFromString(text);
else
return Activator.CreateInstance(type);
}
Use like so;
bd.Budget = objReader[i].ToString().ParseAny(typeof(double));
// Examples
int intTest = "1234".ParseAny(typeof(int)); // Result: 1234
double doubleTest = "12.34".ParseAny(typeof(double)); // Result: 12.34
decimal pass = "12.34".ParseAny(typeof(decimal)); // Result: 12.34
decimal fail = "abc".ParseAny(typeof(decimal)); // Result: 0
string nullStr = null;
decimal failedNull = nullStr.ParseAny(typeof(decimal)); // Result: 0
Optional
On a side note, if that's an SQLDataReader you may also make use of GetSafeString extension(s) to avoid null exceptions from the reader.
public static string GetSafeString(this SqlDataReader reader, int colIndex)
{
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
public static string GetSafeString(this SqlDataReader reader, string colName)
{
int colIndex = reader.GetOrdinal(colName);
if (!reader.IsDBNull(colIndex))
return reader.GetString(colIndex);
return string.Empty;
}
Use like so;
bd.Budget = objReader.GetSafeString(i).ParseAny(typeof(double));
bd.Budget = objReader.GetSafeString("ColumnName").ParseAny(typeof(double));
I had the same problem (5 minutes ago) and I solved it using old style properties with getter and setter, whose use variables.
My code:
public List<int> bigField = new List<int>();
public List<int> BigField { get { return bigField; } set { bigField = value; } }
So, I just used bigField variable. I'm not the programmer, if I misunderstood the question, I'm really sorry.

Categories

Resources