While writing the code, I found that the results were different from those when we checked break points. The likely cause is the ToString function, which has different results when override. Why is the result different when you check break point after override?
When checking break point, call the function internally but do not know why.
My Code
using System;
namespace Test
{
class Program
{
static void Main(string[] args)
{
TestClass testClass = new TestClass();
Console.Write("Test"); // Break Point
Console.ReadKey();
}
}
public class TestClass
{
public override string ToString()
{
Console.WriteLine("???");
return null;
}
}
}
The results are as follows.
Check break point:
???
Test
Non:
Test
When you inspect testClass with the debugger, ToString() will be called by the debugger. This prints "???" to the console.
Related
Recently I was browsing one C# program and stumbled across some weird behavior of a class inside of it. I wrote a little program to outline this behavior:
class Program
{
static void Main()
{
Test inst1 = new Test();
inst1.name0 = "Hello";
inst1.name1 = "World";
Console.WriteLine(inst1.ToString());
Console.WriteLine(inst1);
}
}
class Test
{
public string name0;
public string name1;
public override string ToString()
{
return string.Format("Name0: {0}; Name1: {1}", name0 ?? "(null)", name1 ?? "(null)");
}
}
Output:
Name0: Hello; Name1: World
Name0: Hello; Name1: World
So why do inst1.ToString() and inst1 return the same value in WriteLine() method? I'm confused.
When passed an object, the Console.WriteLine overload will use the object's ToString method.
From the documentation,
If value is null, only the line terminator is written. Otherwise, the ToString method of value is called to produce its string representation, and the resulting string is written to the standard output stream.
This happens because the Test class overrides the ToString function.
When Console.Writeline has to display a non String object, it will look for the ToString function and use it if available.
I want to use a function from another class within a new function which I will call from main. I am trying to do this as below, but get an error:
Error The name 'Class1' does not exist in the current context.
Actually, in my code I use different names, but its just to illustrate the structure and to make it easier to read for you.
public class Class1
{
public static int[] Function1()
{
// code to return value
}
}
public class Class2
{
public static int Function2()
{
int[] Variable = Class1.Function1();
//other code using function1 value
}
}
Actually, in my code I use different names, but its just to illustrate the structure and to make it easier to read for you.
Unfortunately you've made it so easy to read that you have eliminated the problem entirely! The code you posted does not contain an error and is perfectly valid.
The error message is very clear; from wherever you are actually calling the code, "Class1" (or whatever it may be) is not in scope. This may be because it is in a different namespace. It may also be a simple typo in your class name. Does your code actually look something like this?
namespace Different
{
public class Class1
{
public static int[] Function1()
{
// code to return value
}
}
}
namespace MyNamespace
{
class Program
{
static void Main(string[] args)
{
// Error
var arr = Class1.Function();
// you need to use...
var arr = Different.Class1.Function();
}
}
}
That's the best I got until you post the actual code.
I have the following code:
[Serializable]
class ExceptionAspectHandler:OnExceptionAspect
{
public override void OnException(MethodExecutionArgs args)
{
Console.WriteLine("{0}", args.Exception);
args.FlowBehavior = FlowBehavior.Continue;
}
}
[OnExceptionAspect]
public static void divide()
{
int n = Convert.ToInt32(Console.ReadLine());
var a = 100 / n; //the exception happens here
Console.WriteLine("it should get here");
}
Using FlowBehavior.Continue ends divide() and returns to the main() method.
Remember, the OnException aspect wraps your code in a try/catch so the code will continue from the catch (instead of rethrowing) and it's behavior will default to return. Are you wanting it to continue from where it threw the exception? If so, you need to explicitly wrap that line in a try/catch yourself.
Please read http://www.sharpcrafters.com/blog/post/Day-6-Your-code-after-PostSharp.aspx for more details.
The attribute used in divide() method should be ExceptionAspectHandler (you've created), not OnExceptionAspect.
I set up a simple program just to test how the code inside a get accessor executes (since I had been having some issues in another project), and found something quite strange:
class Program {
static void Main(string[] args) {
var test = new TestClass();
var testBool = test.TestBool;
}
}
public class TestClass {
private bool _testBool = true;
public bool TestBool {
get {
if (_testBool) {
Console.WriteLine("true!");
} else {
Console.WriteLine("false! WTF!");
}
_testBool = false;
return _testBool;
}
}
}
I expected the output to be
true!
But what I got instead was
true!
false! WTF!
Just what is going on here?
If I had to guess, I'd say that the debugger ran it once to show the members of a local variable in the IDE.
If you have side effects in properties (which you shouldn't), don't run it in the IDE :)
Try it at the console; it should behave itself there.
No repro.
And don't write Getters with side effects.
Consider the following code:
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var square = new Square(4);
Console.WriteLine(square.Calculate());
}
}
class MathOp
{
protected MathOp(Func<int> calc) { _calc = calc; }
public int Calculate() { return _calc(); }
private Func<int> _calc;
}
class Square : MathOp
{
public Square(int operand)
: base(() => _operand * _operand) // runtime exception
{
_operand = operand;
}
private int _operand;
}
}
(ignore the class design; I'm not actually writing a calculator! this code merely represents a minimal repro for a much bigger problem that took awhile to narrow down)
I would expect it to either:
print "16", OR
throw a compile time error if closing over a member field is not allowed in this scenario
Instead I get a nonsensical exception thrown at the indicated line. On the 3.0 CLR it's a NullReferenceException; on the Silverlight CLR it's the infamous Operation could destabilize the runtime.
It was a compiler bug that has been fixed. The code should never have been legal in the first place, and if we were going to allow it, we should have at least generated valid code. My bad. Sorry about the inconvenience.
It's not going to result in a compile-time error because it is a valid closure.
The problem is that this is not initialized yet at the time the closure is created. Your constructor hasn't actually run yet when that argument is supplied. So the resulting NullReferenceException is actually quite logical. It's this that's null!
I'll prove it to you. Let's rewrite the code this way:
class Program
{
static void Main(string[] args)
{
var test = new DerivedTest();
object o = test.Func();
Console.WriteLine(o == null);
Console.ReadLine();
}
}
class BaseTest
{
public BaseTest(Func<object> func)
{
this.Func = func;
}
public Func<object> Func { get; private set; }
}
class DerivedTest : BaseTest
{
public DerivedTest() : base(() => this)
{
}
}
Guess what this prints? Yep, it's true, the closure returns null because this is not initialized when it executes.
Edit
I was curious about Thomas's statement, thinking that maybe they'd changed the behaviour in a subsequent VS release. I actually found a Microsoft Connect issue about this very thing. It was closed as "won't fix." Odd.
As Microsoft says in their response, it is normally invalid to use the this reference from within the argument list of a base constructor call; the reference simply does not exist at that point in time and you will actually get a compile-time error if you try to use it "naked." So, arguably it should produce a compile error for the closure case, but the this reference is hidden from the compiler, which (at least in VS 2008) would have to know to look for it inside the closure in order to prevent people from doing this. It doesn't, which is why you end up with this behaviour.
How about this:
using System;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var square = new Square(4);
Console.WriteLine(square.Calculate());
}
}
class MathOp
{
protected MathOp(Expression<Func<int>> calc) { _calc = calc.Compile(); }
public int Calculate() { return _calc(); }
private Func<int> _calc;
}
class Square : MathOp
{
public Square(int operand)
: base(() => _operand * _operand)
{
_operand = operand;
}
private int _operand;
}
}
Have you tried using () => operand * operand instead? The issue is that there's no certainty that _operand will be set by the time you call the base. Yes, it's trying to create a closure on your method, and there's no guarantee of the order of things here.
Since you're not setting _operand at all, I'd recommend just using () => operand * operand instead.