开发者

Cannot access a non-shared member of a class in C#, but can in VB?

I`m just started learning C#, used to be a VB programmer开发者_运维问答.

In VB.NET, it is possible to access a form class method, even if this method is not declared as shared. In the code below, I don`t get compiler errors, and calling the method Foo inside ClassFoo works ok.

Public Class Form1
    Public Sub Foo()
        MsgBox("Test")
    End Sub
End Class

Public Class ClassFoo
    Sub Foo()
        Form1.Foo()
    End Sub
End Class

Then, I tried to port the same code to C#, but I get an error:

"An object reference is required for non-static field and bla bla bla".

Why I can access a method not shared in VB and can`t in C#?


This is a rather horrific feature inherited from VB6, a language that allowed this construct. It is not allowed in a pure OOP language, referencing a member of an object requires an object name, not a type name.

The VB.NET team went through some trouble to make this work in the VB.NET language. "Form1" in this statement is in fact an object reference, one that gets auto-generated by the compiler. Something that goes horribly wrong when that name is used in threads btw.

But this won't fly in the C# language, you have to supply an object reference. You will have to re-factor the code so the ClassFoo object has that reference. Something like this:

public class Form1 {
    ClassFoo fooObj;
    public Form1() {
        fooObj = new ClassFoo(this);
    }
    public void Foo() {
        MessageBox.Show("un-fooed");
    }
}

public class ClassFoo {
    Form1 mainForm;
    public ClassFoo(Form1 main) {
        mainForm = main;
    }
    public void Foo() {
        mainForm.Foo();
    }
}

This is probably going to cause some pain while you are learning C#. The Q&D workaround for this is to use Application.OpenForms. Avoid using it if you prefer to byte the bullet.


You shouldn't be able to in VB. I copied and pasted your sample vb code and it gives the same compile error.

Shared in VB is Static in C# Aside from the keyword, the behavior is the same. If you want to access a member without creating an instance of that class, it needs to be static (shared in vb).


In C# Shared is actually Static

Your port should be:

public class Form1
{
   public static void Foo()
   {
       MessageBox.Show("Test");
   }
}

public class ClassFoo
{
   public void Foo()
   {
      Form1.Foo();
   }
}

Static methods / fields / properties / etc don't require an instance to use, they are members of the class itself. Another Example:

public class MyClass
{
    protected MyClass() { /* Do Something */ }
    public static MyClass Create(string someParam)
    {
        /* Do something with someParam */
        return new MyClass();
    }
}

Then:

MyClass a = new MyClass(); // Error, Constructor is protected
MyClass b = MyClass.Create("Foobar"); // Works, calls the `static` method

Update: In response to your comment:

<snarky-answer>Because vb is horrible?</snarky-answer> No really, this looks like a disaster waiting to happen.

If you dont declare your sub as shared, and you try to access instance variables, it'll blow up. In C# if you try to access non-static members from a static method, it'll give you a compile time error, and thus such bad code doesn't make it into production.

As for why you can do it, that's a question for the Microsoft Team. The real thing is that you shouldn't do it!


For the record, I tried to compile your code:

Cannot access a non-shared member of a class in C#, but can in VB?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜