views:

76

answers:

3

Background: I have enclosed (parent) class E with nested class N with several instances of N in E. In the enclosed (parent) class I am doing some calculations and I am setting the values for each instance of nested class. Something like this:

n1.field1 = ...;
n1.field2 = ...;
n1.field3 = ...;
n2.field1 = ...;
...

It is one big eval method (in parent class). My intention is -- since all calculations are in parent class (they cannot be done per nested instance because it would make code more complicated) -- make the setters only available to parent class and getters public.

And now there is a problem:

  • when I make the setters private, parent class cannot acces them
  • when I make them public, everybody can change the values
  • and C# does not have friend concept
  • I cannot pass values in constructor because lazy evaluation mechanism is used (so the instances have to be created when referencing them -- I create all objects and the calculation is triggered on demand)

I am stuck -- how to do this (limit access up to parent class, no more, no less)?


I suspect I'll get answer-question first -- "but why you don't split the evaluation per each field" -- so I answer this by example: how do you calculate min and max value of a collection? In a fast way? The answer is -- in one pass. This is why I have one eval function which does calculations and sets all fields at once.

A: 

make the fields "protected internal"

if the nested classes are private you could use obly "internal" to those fields.

Jack
Won't the fields be exposed to whole assembly?
macias
in case of "internal field and private class": no because the class is private.the other case: yes it would. but the own assembly should be under your control. usually that is not a problem.
Jack
Actually it is always a problem -- one year later, you can have the same best intention, but you could forget the design. The code should reflect the design, not comments or wishes.
macias
+3  A: 
Codesleuth
Thank you, but it is a single file, not that big, so it seems like a bit of overkill setting this separate assembly.
macias
Updated my answer based upon Thomas Levesque's answer.
Codesleuth
Beauty (the interface can be nested). THANK YOU!
macias
+4  A: 

You could declare inside E a private interface IN, explicitly implemented by N. This interface would expose the members of N accessible only by E :

public class E
{
    public void Foo()
    {
      IN n = new N();
      n.Field1 = 42;
    }

    public class N : IN
    {
        private int _field1;

        int IN.Field1
        {
            get { return _field1; }
            set { _field1 = value; }
        }
    }

    private interface IN
    {
        int Field1 { get; set; }
    }
}
Thomas Levesque
Thank you. Interface cannot be made private because I won't read the values outside the parent class (I need public getters), and once it is public I can also use setters publicly.
macias
I think you misunderstood my answer... the `IN` interface is never intended to be public. It is only a way for the nested class to expose properties only to the containing class. You can also create public getters in `N` if you need them
Thomas Levesque
If the interface is private it is not available outside the parent class.
macias
well, yes, that's the point... that way, only the parent class can set the nested class private fields
Thomas Levesque