Passing delegate to a constructor not working - c#

I'm trying to pass a delegate as a parameter in the ctor of a class like this
class Foo
{
protected delegate void CreateResource(object parameter);
protected Foo(CreateResource res)
{
}
public Foo(string resourceName)
: this(CreateStreamRes) // Compiler error
{
}
protected void CreateStreamRes(object o)
{
}
}
But I get the following compiler error in the commented line: "An object reference is required for the non-static field, method, or property 'CreateStreamRes(object)'".
However if I Add a variable inside the constructor like this
public Foo(string resourceName)
: this(CreateStreamRes) // Compiler error
{
CreateResource cr = CreateStreamRes; // OK
}
it compiles that line successfully.
It seems like the C# treats the constructor as a static method. Because if I add the static keyword to the CreateStreamRes(object o) method it compiles nice.
Can someone explain me why is this happening?

You cannot use a non-static method there, because the object hasn't been constructed yet! Just define CreateStreamRes as static and be done with it!
Now, I'm sure Eric Lippert can give you a proper explanation about why this is the case, but I think of it like this: Using the :this() syntax will get translated into calling that constructor first and then doing whatever is in the constructor body afterwards. So you can't really use instance methods on an object that doesn't exist yet, right?
You could factor out the portion body of the constructor and call that:
class Foo
{
protected delegate void CreateResource(object parameter);
protected Foo(CreateResource res)
{
Initialize(res);
}
protected void Initialize(CreateResource res)
{
}
public Foo(string resourceName)
{
Initialize(CreateStreamRes(res));
}
protected void CreateStreamRes(object o)
{
}
}
This works, because by the time you call Initialize, the object has been allocated. Inside the constructor you are free to use instance methods.

You cannot call instance method when calling the :this() keyword. That's because the instance of the class is not yet created. If you need to invoke some method there it must be static.

Related

Can I call a constructor from same class method in C#?

Can I call a constructor from same class method in C#?
Example:
class A
{
public A()
{
/* Do Something here */
}
public void methodA()
{
/* Need to call Constructor here */
}
}
The short answer is No :)
You cannot call constructors as simple methods except these special cases:
You create a new object: var x = new ObjType()
You call a constructor from another constructor of the same type:
class ObjType
{
private string _message;
// look at _this_ being called before the constructor body definition
public ObjType() :this("hello")
{}
private ObjType(string message)
{
_message = message;
}
}
You call a base type constructor from a constructor:
class BaseType
{
private string _message;
// NB: should not be private
protected BaseType(string message)
{
_message = message;
}
}
class ObjType : BaseType
{
// look at _base_ being called before the constructor body execution
public ObjType() :base("hello")
{}
}
UPD. Regarding the workaround with an initialization method proposed in another answer - yes, it's probably a good way. But it's a bit tricky because of the object consistency, which is the reason why constructors are even exist. Any object method is expected to receive the object (this) in a consistent (working) state. And you cannot guarantee it calling a method from a constructor. So any person editing that initialization method or calling constructor in future (probably you) could expect having this guarantee which greatly increases the risk of making mistake. The problem is amplified when you deal with inheritance.
Besides provided answer which answers the question, an easy away to fix your problem is to define an initialization method that is called from both the constructor and your method:
class A
{
private init()
{
// do initializations here
}
public A()
{
init();
}
public void methodA()
{
// reinitialize the object
init();
// other stuff may come here
}
}
Shortly put, you cannot call the constructor, but you don't have to :)

How to prevent shadowing and promote given method?

In C++ it is done with "using", and in C#?
public class foo
{
public void print(string s) {...}
}
public class bar : foo
{
// shadowing
public void print(object o) {...}
}
How to promote foo.print, so foo.print and bar.print would be at the same "level" for compiler (for bar of course)?
Update 1
Originally I added a paragraph about common confusion between shadowing and overriding, but then I deleted it, because I thought it will be offensive to readers.
Shadowing is like overloading spanned over inheritance tree. Shadowing is NOT overriding.
Update 2
After shadowing foo.print is no longer taken into account when resolving the overloaded method print. Promoting foo.print would get it back into process -- so when I call bar_object.print("hello") the method foo.print would be called.
In your concrete example, bar.print(object) indeed "shadows" the more specific foo.print(string):
new bar().print("i am a string");
This will call the method defined on bar, although the method on foo would have a parameter that matches the type better.
What happens here is the following: The compiler finds a method on bar with the right name ("print"), the right number of parameters (1) and a parameter type to which the passed in parameter is convertable to (string can be converted to object).
Because of this, there is no reason for the compiler to look further up the inheritance chain.
As far as I am aware, there is no construct similar to C++'s using.
If you want to use the method defined on the base class, you basically have three options:
On the caller side: Convert the bar instance to foo:
var bar = new bar();
var foo = (foo)bar;
foo.print("i am a string"); // Will call foo.print(string)
On the calee side: Inside bar.print(object) check the type of the passed parameter:
public void print(object o)
{
var s = o as string;
if(s != null)
base.print(s);
else
{
// Other code.
}
}
This will come the closest to the C++ using: Actually override or hide the original method in the derived class:
public class bar : foo
{
public new void print(string s)
{
base.print(s);
}
public void print(object o)
{
// some code
}
}

Oveloaded function static method error

I was going through an example which is below
class Program
{
public static void Show(String pstrMessage)
{
Console.WriteLine(pstrMessage);
}
public void Show(Object obj)
{
Console.WriteLine(obj.ToString());
}
static void Main(string[] args)
{
Program program=new Program();
program.Show("Test Message");
}
}
When I remove the static function it is working fine. Other wise it is giving me a compile time error.can't access Static method "show" in non static context.As I think object is the base class for all then it should automatically typecasted to object (implicit typcasting).
Can anyone explain why it is giving an error.
Thanks
There's no reason for Show(Object) to be a non-static member function. Declare that function static too.
Then, you'll need to use Program.Show (with the class name) instead of program.Show (with the instance name) because you're calling a static function.
When multiple method names match, the compiler runs an overload resolution procedure to decide which method is more specific. In your case, the static overload happens to be the most specific one, because it takes a string rather than object. The compiler complains that you should be calling it using Program.Show("Test Message");
If you want to use the instance function, just using program.Show((Object)"Test Message");

Can somebody explain this C# constructor syntax - public Class1(Class 2 Obj) : this(obj.ToString())?

Here is the code:
class Class1
{
private Class2 object;
public Class1(Class2 obj) : this(obj.ToString())
{
this.object = obj;
}
}
More specifically, what does the : this part do.
The :this(obj.ToString) causes the constructor code for the constructor defined taking a string parameter to run first. Once it runs, then the constructor code (setting this.object = obj) is executed.
This is covered in MSDN's page on Constructors (the last example set).
Note that, in your code above, as written, this will cause a compiler error. You would also need to have a constructor like the following:
public Class1(string str) // Constructor taking a string, though it could be non-public
{
// Do something with str
}
With this constructor in place, it will get called, perform it's initialization steps, then the first constructor (which sets this.object) will run.
: this(obj.ToString()) calls overloaded version of constructor from same class.
It means that somewhere in this class you have another constructor which takes string as parameter and will be executed alongside current constructor.
class A
{
public A(Class2 obj): this(obj.ToString()) // execute A(string text)
{
// your code
}
public A(string text)
{
// your code
}
}
Class 1 will have another constructor that takes a string parameter.
It calls the constructor that matches that syntax. In your case, I'm assuming there's a constructor that takes a string argument somewhere:
public Class1(string s)
{
}

CS0120 error under vs2010 beta 2 - object reference is required

the following code used to work fine under vs2008:
namespace N2.Engine.Globalization
{
public class DictionaryScope : Scope
{
object previousValue;
public DictionaryScope(IDictionary dictionary, object key, object value)
: base(delegate
{
if (dictionary.Contains(key))
previousValue = dictionary[key];
dictionary[key] = value;
}, delegate
{
if (previousValue == null)
dictionary.Remove(key);
else
dictionary[key] = previousValue;
})
{
}
}
}
but now it reports An object reference is required for the non-static field, method, or property 'N2.Engine.Globalization.DictionaryScope.previousValue'
It seems something changed in the compiler? Any workarounds?
update:
regarding the suggestion to use a virtual method. This probably wouldn work either, as the virtual method would get called from the base constructor, which I believe is also not possible?
Here is the implementation of the Scope (base class):
public class Scope: IDisposable
{
Action end;
public Scope(Action begin, Action end)
{
begin();
this.end = end;
}
public void End()
{
end();
}
#region IDisposable Members
void IDisposable.Dispose()
{
End();
}
#endregion
Update:
ยง 7.5.7 This access
A this-access consists of the reserved word this.
this-access:
this
A this-access is permitted only in the block of an instance constructor, an instance method, or an instance accessor.
This is none of these. The 4.0 compiler looks to be correct. Presumably it isn't happy because this in essence provides access to this at a point when the type isn't initialized. Maybe ;-p
Note that I expect that it isn't really the this.someField that causes this - more that the use of a field causes this to be captured, meaning it wants to hoist the this instance onto a compiler-generated class - as though you had written:
public MyCtor() : base( new SomeType(this).SomeMethod ) {...}
The C# 3.0 compiler spots the above abuse of this.
Reproduced. Investigating. It looks like an issue resolving the implicit this in the constructor chaining.
The most likely workaround would be to use a virtual method instead of a delegate, and simply override it in the derived class.
One workaround would be to pas the instance in as an argument, so the delegate becomes "obj => obj.whatever...", and use theDelegate(this);.
Simpler repro:
public class MyBase {
public MyBase(Action a) { }
}
public class MySub : MyBase {
private string foo;
// with "this.", says invalid use of "this"
// without "this.", says instance required
public MySub() : base(delegate { this.foo = "abc"; }) { }
}
I would need to check the spec, but I'm not sure whether this is valid in this context... so the 4.0 compiler could be correct.
Add:
static object previousValue;

Categories