10

I am fairly new to C# programming so this is likely a beginner's question.

I get a "'A.Test.That.Fails' is inaccessible due to its protection level" error on the following code snippet and I fail to understand the reason.

namespace A
{
    class Test
    {
        public void Demo()
        {
            That[] it = new That[42];
            it[0].fails = 21;
        }

        public struct That
        {
            int fails;
        }
    }
}

Coming from C++ programming and having read that protection rules are almost the same, since there is a single class I would expect it to work even if both the That struct and the Demo method were private.

As the side note, a link to some page summing up scope and protection rules toward the C++ programmer would be greatly appreciated.

Julien Guertault
  • 1,324
  • 1
  • 12
  • 24
  • 15
    `A.Test.That.fails`... clever. +1 – BoltClock Mar 28 '11 at 08:43
  • 2
    See Cody's answer; there is a big difference between structs and classes in C#; they are barely related, in fact. Most times that people use a struct in C#, it is incorrect. Make sure you are using it for the right reason. "Because it is a simple object" is not such a reason. – Marc Gravell Mar 28 '11 at 08:55
  • @BoltClock: ;) @Marc: will "because I just want a quick array of scalar pairs" do as an excuse? – Julien Guertault Mar 28 '11 at 09:02
  • Yes, I'd say so. Not necessarily because it's simple or quick, but because you want value type semantics for those scalar pairs. They should work just like a regular `int`, not like an object. It makes logical sense that they be immutable. I'd choose a struct for that, too. – Cody Gray Mar 28 '11 at 09:05
  • 1
    On a tangential note: In the case that you don't *want* your internals public but need them to be public anyhow, `InternalsVisibleTo` allows you to make an internal class visible to a specific external assembly. This is mostly useful for unit-testing. – Brian Mar 28 '11 at 15:19

5 Answers5

11

The other answers given already have your answer, so I won't beat a dead horse here. You need to declare the field public in order to be able to access it from external code.

In C++, structs and classes are equivalent, with the only difference being the default access level of their respective members.

However, that's not the case in C#. Generally, you should only use a struct for small, short-lived objects that are immutable (won't change). A structure has value type semantics, where as a class has reference type semantics. It's very important that you understand the difference between value types and reference types if you're learning to program in C#. Jon Skeet has published an article that attempts to provide that explanation. But you'll definitely want to pick up a good introductory book to C# that treats these issues in more detail.

More often than not, you'll want to use a class in C#, rather than a structure. And when you use that class, note that Microsoft's design guidelines for C# tend to recommend against exposing public fields. Instead, they recommend that you use a public property, backed by a private field. A more thorough exposition of the rationale behind that guideline is given here. For example:

class TimePeriod
{
    private double seconds;

    public double Seconds
    {
        get { return seconds; }
        set { seconds = value; }
    }
}

Or you can use the simpler "automatic properties" syntax, which has the compiler automatically generate that private backing field:

class TimePeriod
{
    public double Seconds { get; set; }
}
Cody Gray
  • 222,280
  • 47
  • 466
  • 543
  • Yep, for the sake of the example I did put public, but in real life things go as private as possible indeed, and this ability to define set/get clearly helps. Thank you for the overview and link. – Julien Guertault Mar 28 '11 at 08:55
  • 1
    @Julien: Of course. I assumed the example was contrived for demonstration purposes only. Obviously in the real world there are indeed legitimate cases where you want to use a struct. Not only for value type semantics, but also for interop purposes. But in general, objects are best modeled using a class in C#. – Cody Gray Mar 28 '11 at 08:57
  • +1 Win32 interop has forced me into egregious use of structs in my WPF app... and I'm detesting it. – BoltClock Mar 28 '11 at 08:59
  • @Bolt: But of course, I assume that you've placed all those structs in a separate namespace and/or assembly, and declared them either private or internal. I always write a nice, clean managed wrapper class over the interop code, which is the only thing I expose publically. – Cody Gray Mar 28 '11 at 09:03
4

The default access modifier in C# for struct fields (and class fields) is private. So int fails; is private to your struct, unless you declare it public.

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
2

please see the answer to this question

That member is being declared private by default - you need to put the public modifier before it.

Community
  • 1
  • 1
Andras Zoltan
  • 40,853
  • 11
  • 98
  • 156
2

Because fails is not public.. by default fields in struct and even class are private

According to MSDN

The access level for class members and struct members, including nested classes and structs, is private by default.

Shekhar_Pro
  • 17,252
  • 7
  • 47
  • 77
1

Private members of Test restrict to Test itself and are not available outside of Test. Demo is outside of Test. It doesn't matter who the parent is.

Define Demo inside Test and you can access the private members.

Stephen Chung
  • 14,113
  • 1
  • 30
  • 47
  • Of course. It is not inside the definition of Test, so it is outside. QED. To be inside it needs to be within the braces of the Test struct itself. – Stephen Chung Mar 28 '11 at 08:42