Read-only ("const"-like) function parameters of C# - c#

Coming from a C++ background, I'm used to sticking the const keyword into function definitions to make objects being passed in read-only values. However, I've found out that this is not possible in C# (please correct me if I'm wrong). After some Googling, I arrived at the conclusion that the only way to make a read-only object is to write an interface that only has 'get' properties and pass that in instead. Elegant, I must say.
public interface IFoo
{
IMyValInterface MyVal{ get; }
}
public class Foo : IFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
}
}
I would pass it into:
public void SomeFunction(IFoo fooVar)
{
// Cannot modify fooVar, Excellent!!
}
This is fine. However, in the rest of my code, I would like to modify my object normally. Adding a 'set' property to the interface would break my read-only restriction. I can add a 'set' property to Foo (and not IFoo), but the signature expects an interface rather than a concrete object. I would have to do some casting.
// Add this to class Foo. Might assign null if cast fails??
set { _myVal = value as ConcreteMyVal; }
// Somewhere else in the code...
IFoo myFoo = new Foo;
(myFoo as Foo).MyFoo = new ConcreteMyVal();
Is there a more elegant way of replicating const or making read-only function parameters without adding another property or a function?

I think you may be looking for a solution involving two interfaces in which one inherits from the other:
public interface IReadableFoo
{
IMyValInterface MyVal { get; }
}
public interface IWritableFoo : IReadableFoo
{
IMyValInterface MyVal { set; }
}
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public IMyValInterface MyVal
{
get { return _myVal; }
set { _myVal = value as ConcreteMyVal; }
}
}
Then you can declare methods whose parameter type “tells” whether it plans on changing the variable or not:
public void SomeFunction(IReadableFoo fooVar)
{
// Cannot modify fooVar, excellent!
}
public void SomeOtherFunction(IWritableFoo fooVar)
{
// Can modify fooVar, take care!
}
This mimics compile-time checks similar to constness in C++. As Eric Lippert correctly pointed out, this is not the same as immutability. But as a C++ programmer I think you know that.
By the way, you can achieve slightly better compile-time checking if you declare the type of the property in the class as ConcreteMyVal and implement the interface properties separately:
public class Foo : IWritableFoo
{
private ConcreteMyVal _myVal;
public ConcreteMyVal MyVal
{
get { return _myVal; }
set { _myVal = value; }
}
public IMyValInterface IReadableFoo.MyVal { get { return MyVal; } }
public IMyValInterface IWritableFoo.MyVal
{
// (or use “(ConcreteMyVal)value” if you want it to throw
set { MyVal = value as ConcreteMyVal; }
}
}
This way, the setter can only throw when accessed through the interface, but not when accessed through the class.

The closest equivalent is the in keyword. Using in makes the parameter and input parameter and prevents it from being changed inside the method. From the official C# documentation:
in - specifies that this parameter is passed by reference but is only read by the called method.
ref - specifies that this parameter is passed by reference and may be read or written by the called method.
out - specifies that this parameter is passed by reference and must be written by the called method.

First of all, you're correct: you cannot apply const or a similar keyword to parameters in C#.
However, you can use interfaces to do something along those lines. Interfaces are special in the sense, that it makes perfect sense to make an interface that only covers a specific part of a feature set. E.g. image a stack class, which implements both IPopable and IPushable. If you access the instance via the IPopable interface, you can only remove entries from the stack. If you access the instance via the IPushable interface, you can only add entries to the stack. You can use interfaces this way to get something similar to what you're asking for.

Consider Timwi's answer first. But as a second option, you could do this, making it more like the C CONST keyword.
Reference-type (object) parameters are IN parameters by default. But because they are references, their method side effects and property accesses are done to the object outside the method. The object doesn't have to be passed out. It has still been modified by the method.
However, a value-type (struct) parameter is also IN by default, and cannot have side effects or property modifications on the element that was passed in. Instead, it gets COPIED ON WRITE before going into the method. Any changes to it inside that method die when the method goes out of scope (the end of the method).
Do NOT change your classes to structs just to accommodate this need. It's a bad idea. But if they should be structs anyway, now you'll know.
BTW, half the programming community doesn't properly understand this concept but thinks they do (indeed, I've found inaccuracies on the matter of parameter direction in C# in several books). If you want to comment on the accuracy of my statements, please double check to make sure you know what you're talking about.

Related

Implement a generic type to pass around

I am sure this is duplicate but I am not sure I am searching for the correct answers. Or understanding that it answers my question.
For 1 I think I am using my interface wrong. For 1 I break the rules of SOLID and am trying to clean it up. For example IReelWindow. I have things in there specific to ReelWindowTumble that the other ReelWindows don't use and throw not implemented errors. I started breaking it up into multiple interfaces but found i no longer had access to functions for ReelWindowTumble, even though I created a new interface for ITumble and still inherited from IReelWindow. The problem is in the functional code.
public interface IReelWindow
{
//stuff declared
void PopulateWindowTumble();
void PopulateWindow(int[] currentStops);
}
public class ReelWindow : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
public void PopulateWindowTumble()
{
throw new NotImplementedException();
}
}
public class ReelWindowTumble : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
void PopulateWindowTumble()
{
}
}
public class ReelWindowIndependent : IReelWindow
{
// implements most of it throwing exceptions when I don't use it.
public void PopulateWindow(int[] currentStops)
{
}
public void PopulateWindowTumble()
{
throw new NotImplementedException();
}
}
Here I declare a new IReelWindow and create a new ReelWindow based on client input. This works ok, as I just pass IReelWindow everywhere I want to use a ReelWindow.
I don't think this is the proper usage of my interface. If I use ICloneable, i don't declare a new object of ICloneable and pass it around.
But my intention is to create a Generic ReelWindow Type. I don't care what type of window the client creates. I just want to enforce what functions it should have as I use them specifically.
How do I declare a Generic ReelWindow that I can pass around without creating multiple functions that are identical but have strong types passed in?
public static IReelWindow CreateReelWindow(WindowType userSelectedWindowType, Paytable paytable)
{
IReelWindow _reelWindow;
if (userSelectedWindowType == WindowType.Standard)
{
_reelWindow = new ReelWindow(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop);
}
else if (userSelectedWindowType == WindowType.Tumble)
{
_reelWindow = new ReelWindowTumble(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop);
}
else if (userSelectedWindowType == WindowType.Independent)
{
_reelWindow = new ReelWindowIndependent(paytable.ColLengths, paytable.ReelContainer.Reels, paytable.WindowWidth, paytable.Lineset, paytable.ReelContainer.TotalPhysicalReelStop, paytable.ReelLengths, paytable.ReelStarts);
}
else
throw new ApplicationException("Unknown window type selected by user. Cannot continue.");
return _reelWindow;
}
Later in my code I use the reelwindows, and only pass in 'IReelWindow' as I don't care what type of reelwindow, the function will use it accordingly.
public abstract class AEval
{
public abstract double Evaluate(IReelWindow reelWindow, ref string flags, int currentStopsWeight);
public abstract double EvaluateVerbose(IReelWindow reelWindow, ref string flags, int currentStopsWeight);
}
The object that you are passing around is _reelWindow and while it implements IReelWindow, it is not an IReelWindow object. Instead it is one of your derived types: ReelWindow, ReelWindowTumble, ReelWindowIndependent, etc. Each of those derived types should be treated the same by your client (as you noted).
Let's pretend ReelWindow implements 2 methods from the interface, ReelWindowTumble implements 3 methods from the interface, and ReelWindowIndependent implements 10 methods from the interface. And the interface has a maximum of 10 methods to implement.
Using the language of your example, that means that ReelWindow will have 8 methods with NotImplementedException (NIE), ReelWindowTumble will have 7 methods NIE, and ReelWindowIndependent has 0 methods NIE.
What about your client code? Well, for all of this to make sense your client code should be calling all 10 of the interface methods while working with _reelWindow. That also means, using my example, that ReelWindowIndependent should work just fine with the client code because it has no NIE methods.
I'd say that your real problem is the NIE's. Remove those exceptions and instead return null. Then, in your client code, during flow of control, you can add statements to the effect of "if returned object is null, skip this section".
Remember, all objects inherit from 'object'. Those strongly typed return objects in your interface can be returned as 'object' too. That means any strongly typed object can be set to null. To repeat: try returning null value for methods with strongly typed return values and handling the null in your client code. Now, if the interface method has no return - it is marked void - then you don't need to worry about checking for null in your client code, nor would you need NIE: the method can be left blank and when called literally does nothing. If you ponder this, you might strive for interface design that does not use strongly typed return values. And that goes to Jamiec's comment: we need to know more about the interface.

What creational pattern I should use?

My program have two classes; both derive from same base class.
class A : MyBase
{
internal A(InitVal initVal)
}
class B : MyBase
{
internal B(InitVal initVal)
}
InitVal is another class which is injected through constructor. This class is for internal usage. Due to internal constructor, user cannot create instance of class A and B directly. Instead, I created method which creates these objects.
class Initiator
{
InitVal initVal;
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase
{
MyBase myBase = null;
switch(objectInstance)
{
case ObjectInstance.A:
myBase = new A(initVal);
break;
case ObjectInstance.B:
myBase = new B(initVal);
break;
}
return (T)myBase;
}
...
}
ObjectInstance is enum in above code.
This works without problem but I am sure you have never seen such ugly code earlier.
Please suggest creational pattern I should use. I want to remove ObjectInstance enum without changing functionality. It will cleanup much.
I tried Creational Patterns mentioned on dotfactory.
Factory Method and Abstract Factory does not look proper in this case.
My code even though look ugly, it is very simple to read and understand. I tried implementing patterns mentioned above which increases code complexity. So this is also my criteria while choosing answer.
I cannot change anything in code except Initiator class. All other classes are not accessible to me for edit.
Edit 1: Why above code is ugly in my view
1) While calling CreateObject method, user have to specify type of the object twice.
A a = initiator.CreateObject<A>(ObjectInstance.A);
First for T generic value and second to enum value.
I want to avoid this.
2) As user has to specify type of object twice, there are chances of mistake.
A a = initiator.CreateObject<A>(ObjectInstance.B);
In above code, enum value and generic value are different.
This is not allowed and will be a problem.
With my code, I cannot avoid this.
That is why; I am looking for pattern that suits my case without increasing complexity.
If I remove necessity of enum somehow, code will be lot better.
If I can change signature of CreateObject to following, it will be lot better.
public T CreateObject<T>() where T : MyBase
But, I am not sure how I will implement this method to create proper instances.
It doesn't look to me like you are getting any advantage from trying to make this generic. You needs to know the concrete type of the returned value at the call site.
Therefore why not keep things simple and just do this?
public class Initiator
{
InitVal initVal;
public A CreateA()
{
return new A(initVal);
}
public B CreateB()
{
return new B(initVal);
}
}
As you specified the method as generic one, I expect you might actually know the type you want to get already during the compilation time.. so I'd go for something like this:
class Initiator
{
public T CreateObject<T>(ObjectInstance objectInstance) where T : MyBase, new()
{
T newInstance = new T();
newInstance.Value = initVal;
return newInstance;
}
...
}
now you can call it as:
A myAInstance = initiator.CreateObject<A>();
MyBase myAInstance = initiator.CreateObject<A>(); //this also works
To make it work you need to specify an internal parameterless constructor in your classes and specify interface for the Value property or whatever you would set now in your current constructor.
class MyBase{
InitVal Value { get; set;} //this allows construction of the object with parameterless constructor
...
}
This is not only cleaner and shorter, but also less error prone, as you dont need to edit both enum and method body every time new type is added. It gives less flexibility for child-type specific logic, though.
NOTE: If you really want to have constructor with parameters as you have now you still can go for this approach but you'd need to use reflection (check Activator) or lambdas.
Of course this makes only sense if you can decide on the type during compilation time or you if you just want to delegate this decition to a 3rd party library, eg:
switch(chosenType){
case ObjectInstance.A:
instance = initiator.CreateObject<A>();
...
Otherwise, simply leave it as it is, its a FactoryMethod pattern more or less and it does the job. Just that the generic parameter in it... seems to be quite useless then. I would remove it and change return type to MyBase, as user won't be able to specify T anyway.
One last option is to simply create a separate method for each type, this is clean, flexible, gives a lot of options for customization, but sucks if you need to repeat a lot of shared logic and you need to add a new one for each next type. Simply:
A CreateObjectA(InitVal initValue){
return new A(initValue);
}
B CreateObjectB(InitVal initValue){ ...
One obvious problem with your code is the enum, which is unnecessary, because typeof(T) already gives you the appropriate type:
class Initiator
{
readonly Dictionary<Type, Func<MyBase>> _dict = new Dictionary<Type, Func<MyBase>>();
internal Initiator(InitVal initVal)
{
// initialize your "service locator".
// it's cool that different types can have different constructors,
// and people who call CreateObject don't need to know this.
_dict[typeof(A)] = (Func<MyBase>)(() => new A(initVal));
_dict[typeof(B)] = (Func<MyBase>)(() => new B(initVal, someOtherStuff));
}
public T CreateObject<T>() where T : MyBase
{
var ctor = _dict[typeof(T)];
return (T)ctor();
}
}
Alternatively, if you don't know the type, you can pass the enum, but then the return type should be an interface/base class (preferably interface):
// this is more likely, you probably don't need a generic method
public IMyBase CreateObject(ObjectInstance objectInstance)
{
// the dictionary would map enum value to Func<IMyBase>, of course
var ctor = _dict[objectInstance];
return ctor();
}
And now you have a simple "poor man's" DI class called Initiator, so I wonder if your DI framework (the one which injected InitVal) can also inject A and B instances. Which is probably true, since DI purists will tell you there is no place for factories and the new keyword in your code.
Btw, ObjectInstance is a really, really bad name for an enum.
I did it in following way:
class A : IMyType
{
internal A(InitVal initVal)
}
class B : IMyType
{
internal B(InitVal initVal)
}
class Initiator
{
InitVal initVal = .....;
public T CreateObject<T>() where T : IMyType
{
IMyType myType = null;
if(typeof(T) == typeof(A))
myType = new A(initVal);
else if(typeof(T) == typeof(B))
myType = new B(initVal);
else
throw new MyException("Type is not configured.");
return (T)myType;
}
...
}
This resolves the problems I mentioned in my question. But, it creates new problem. This violates open-close principle of SOLID. Last else block handles the manual mistake if any. Anyway, it just works for my specific case; not recommended generally.

can a method parameter pass an object by reference but be read-only?

C#: can you make it so that a method parameter passes an object by reference but is read-only?
eg:
void MyMethod(int x, int y, read-only MyObject obj)
where obj is an object reference but this object cannot be modified during the method.
Can this be achieved in C#?
No. C# has no direct analogue to C++ const (its own const is something different). A common C# pattern for this is to pass in a interface, such as IEnumerable, that does not permit modifications. You can also create an immutable copy or wrapper.
If the class of the object you're passing was written by you, then you're in luck.
Ask yourself: if C# had a const feature, what operations on the object would I expect to be banned through a const reference to my class?
Then define an interface that leaves out the banned operations.
For example:
class MyClass
{
public string GetSomething() { ... }
public void Clobber() { ... }
public int Thing { get { ... } set { ... } }
}
The corresponding "const" interface might be:
interface IConstMyClass
{
public string GetSomething() { ... }
public int Thing { get { ... } }
}
Now amend the class:
class MyClass : IConstMyClass
{
Now you can use IConstMyClass to mean const MyClass.
void MyMethod(int x, int y, IConstMyClass obj)
Note: there will be those who will tell you that this isn't enough. What if MyMethod casts back to MyClass? But ignore them. Ultimately the implementor can use reflection to get around any aspect of the type system - see this amusing example.
The only option to stop reflection attacks is the trivial approach: make a totally disconnected clone.
This is not possible in C#.
You can prevent this by passing in an immutable object.
There is no mechanism that does this for you.
Either pass a throwaway copy, or build immutability, even if temporary, into the class itself.
why don't you make a copy of that object and do whatever you want with that copy while your obj remains not modified.
See here how to clone your object: Deep cloning objects

C# virtual static method

Why is static virtual impossible? Is C# dependent or just don't have any sense in the OO world?
I know the concept has already been underlined but I did not find a simple answer to the previous question.
virtual means the method called will be chosen at run-time, depending on the dynamic type of the object. static means no object is necessary to call the method.
How do you propose to do both in the same method?
Eric Lippert has a blog post about this, and as usual with his posts, he covers the subject in great depth:
https://learn.microsoft.com/en-us/archive/blogs/ericlippert/calling-static-methods-on-type-parameters-is-illegal-part-one
“virtual” and “static” are opposites! “virtual” means “determine the method to be called based on run time type information”, and “static” means “determine the method to be called solely based on compile time static analysis”
The contradiction between "static" and "virtual" is only a C# problem. If "static" were replaced by "class level", like in many other languages, no one would be blindfolded.
Too bad the choice of words made C# crippled in this respect. It is still possible to call the Type.InvokeMember method to simulate a call to a class level, virtual method. You just have to pass the method name as a string. No compile time check, no strong typing and no control that subclasses implement the method.
Some Delphi beauty:
type
TFormClass = class of TForm;
var
formClass: TFormClass;
myForm: TForm;
begin
...
formClass = GetAnyFormClassYouWouldLike;
myForm = formClass.Create(nil);
myForm.Show;
end
Guys who say that there is no sense in static virtual methods - if you don't understand how this could be possible, it does not mean that it is impossible. There are languages that allow this!! Look at Delphi, for example.
I'm going to be the one who naysays. What you are describing is not technically part of the language. Sorry. But it is possible to simulate it within the language.
Let's consider what you're asking for - you want a collection of methods that aren't attached to any particular object that can all be easily callable and replaceable at run time or compile time.
To me that sounds like what you really want is a singleton object with delegated methods.
Let's put together an example:
public interface ICurrencyWriter {
string Write(int i);
string Write(float f);
}
public class DelegatedCurrencyWriter : ICurrencyWriter {
public DelegatedCurrencyWriter()
{
IntWriter = i => i.ToString();
FloatWriter = f => f.ToString();
}
public string Write(int i) { return IntWriter(i); }
public string Write(float f) { return FloatWriter(f); }
public Func<int, string> IntWriter { get; set; }
public Func<float, string> FloatWriter { get; set; }
}
public class SingletonCurrencyWriter {
public static DelegatedCurrencyWriter Writer {
get {
if (_writer == null)
_writer = new DelegatedCurrencyWriter();
return _writer;
}
}
}
in use:
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400.0
SingletonCurrencyWriter.Writer.FloatWriter = f => String.Format("{0} bucks and {1} little pennies.", (int)f, (int)(f * 100));
Console.WriteLine(SingletonCurrencyWriter.Writer.Write(400.0f); // 400 bucks and 0 little pennies
Given all this, we now have a singleton class that writes out currency values and I can change the behavior of it. I've basically defined the behavior convention at compile time and can now change the behavior at either compile time (in the constructor) or run time, which is, I believe the effect you're trying to get. If you want inheritance of behavior, you can do that to by implementing back chaining (ie, have the new method call the previous one).
That said, I don't especially recommend the example code above. For one, it isn't thread safe and there really isn't a lot in place to keep life sane. Global dependence on this kind of structure means global instability. This is one of the many ways that changeable behavior was implemented in the dim dark days of C: structs of function pointers, and in this case a single global struct.
Yes it is possible.
The most wanted use case for that is to have factories which can be "overriden"
In order to do this, you will have to rely on generic type parameters using the F-bounded polymorphism.
Example 1
Let's take a factory example:
class A: { public static A Create(int number) { return ... ;} }
class B: A { /* How to override the static Create method to return B? */}
You also want createB to be accessible and returning B objects in the B class. Or you might like A's static functions to be a library that should be extensible by B. Solution:
class A<T> where T: A<T> { public static T Create(int number) { return ...; } }
class B: A<B> { /* no create function */ }
B theb = B.Create(2); // Perfectly fine.
A thea = A.Create(0); // Here as well
Example 2 (advanced):
Let's define a static function to multiply matrices of values.
public abstract class Value<T> where T : Value<T> {
//This method is static but by subclassing T we can use virtual methods.
public static Matrix<T> MultiplyMatrix(Matrix<T> m1, Matrix<T> m2) {
return // Code to multiply two matrices using add and multiply;
}
public abstract T multiply(T other);
public abstract T add(T other);
public abstract T opposed();
public T minus(T other) {
return this.add(other.opposed());
}
}
// Abstract override
public abstract class Number<T> : Value<T> where T: Number<T> {
protected double real;
/// Note: The use of MultiplyMatrix returns a Matrix of Number here.
public Matrix<T> timesVector(List<T> vector) {
return MultiplyMatrix(new Matrix<T>() {this as T}, new Matrix<T>(vector));
}
}
public class ComplexNumber : Number<ComplexNumber> {
protected double imag;
/// Note: The use of MultiplyMatrix returns a Matrix of ComplexNumber here.
}
Now you can also use the static MultiplyMatrix method to return a matrix of complex numbers directly from ComplexNumber
Matrix<ComplexNumber> result = ComplexNumber.MultiplyMatrix(matrix1, matrix2);
While technically it's not possible to define a static virtual method, for all the reasons already pointed out here, you can functionally accomplish what I think you're trying using C# extension methods.
From Microsoft Docs:
Extension methods enable you to "add" methods to existing types without creating a new derived type, recompiling, or otherwise modifying the original type.
Check out Extension Methods (C# Programming Guide) for more details.
In .NET, virtual method dispatch is (roughly) done by looking at the actual type of an object when the method is called at runtime, and finding the most overriding method from the class's vtable. When calling on a static class, there is no object instance to check, and so no vtable to do the lookup on.
To summarize all the options presented:
This is not a part of C# because in it, static means "not bound to anything at runtime" as it has ever since C (and maybe earlier). static entities are bound to the declaring type (thus are able to access its other static entities), but only at compile time.
This is possible in other languages where a static equivalent (if needed at all) means "bound to a type object at runtime" instead. Examples include Delphi, Python, PHP.
This can be emulated in a number of ways which can be classified as:
Use runtime binding
Static methods with a singleton object or lookalike
Virtual method that returns the same for all instances
Redefined in a derived type to return a different result (constant or derived from static members of the redefining type)
Retrieves the type object from the instance
Use compile-time binding
Use a template that modifies the code for each derived type to access the same-named entities of that type, e.g. with the CRTP
The 2022+ answer, if you are running .Net 7 or above, is that now static virtual members is now supported in interfaces. Technically it's static abstract instead of "static virtual" but the effect is that same. Standard static methods signatures can be defined in an interface and implemented statically.
Here are a few examples on the usage and syntax in .Net 7

How can one type access a private setter of another type's property?

All I need is a way to make a property of one class only 'settable' from one other class (a sort of manager class).
Is this even possible in c#?
My colleague 'reliably' informs me that I have a design flaw, but I feel I should at least ask the community before I concede defeat!
No, it's not really possible to do this in any clean way in C#. You probably have a design flaw ;-)
You can use the internal modifier, which lets all types in the same assembly access the data (or nominated assemblies if using [InternalsVisibleTo] - but no: there is no friend equivalent in C#.
For example:
public string Foo {get; internal set;}
You have a design flaw. Also, don't be paranoid about data hiding. Here's 3.5's way to do it:
class Program
{
static void Main(string[] args)
{
Managed m = new Managed();
Console.WriteLine(m.PrivateSetter);
m.Mgr.SetProperty("lol");
Console.WriteLine(m.PrivateSetter);
Console.Read();
}
}
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(s => PrivateSetter = s)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
}
public class Manager
{
private Action<string> _setPrivateProperty;
public Manager(Action<string> setter)
{
_setPrivateProperty = setter;
}
public void SetProperty(string value)
{
_setPrivateProperty(value);
}
}
Here's how we'd do it in pre-lambda days:
public class Managed
{
private Manager _mgr;
public Manager Mgr
{
get { return _mgr ?? (_mgr = new Manager(this)); }
}
public string PrivateSetter { get; private set; }
public Managed()
{
PrivateSetter = "Unset";
}
public class Manager
{
public void SetProperty(string value)
{
m.PrivateSetter = value;
}
private Managed m;
public Manager(Managed man)
{
m = man;
}
}
}
The best way to do it would be:
/// <summary>
/// Gets or sets foo
/// <b>Setter should only be invoked by SomeClass</b>
/// </summary>
public Object Foo
{
get { return foo; }
set { foo = value; }
}
When you have some complex access or inheritance restriction, and enforcing it demands too much complexity in the code, sometimes the best way to do it is just properly commenting it.
Note however that you cannot rely on this if this restriction has some security implications, as you are depending on the goodwill of the developer that will use this code.
You cannot do that on that way, but you can access a property's setter method from a derived class, so you can use inheritance for the purpose. All you have to do is to place protected access modifier. If you try to do so, your colleague is right :). You can try doing it like this:
public string Name
{
get{ return _name; }
protected set { _name = value; }
}
keep in mind that the set method of the property is only accessible from the derived class.
Or you could have these two classes in an assembly alone and have the setter as internal. I would vote up for the design flaw though, unless the previous answer by milot (inheriting and protected) makes sense.
You could do:
public void setMyProperty(int value, Object caller)
{
if(caller is MyManagerClass)
{
MyProperty = value;
}
}
This would mean that you could use a 'this' pointer from the calling class. I would question the logic of what you're attempting to achieve, but without knowing the scenario I can't advise any futher. What I will say is this: if it is possible to refactor your code to make it clearer, then it is often worthwhile doing so.
But this is pretty messy and certinly NOT fool-proof ... you have been warned!
Alternativly...
You could pass a delegate from the Class with the Property (Class A) to the Manager Class (Class B). The delegate can refer to a private function within A to allow B to call that delegate as any normal function. This precludes that A knows about B and potentially that A is created before B. Again... messy and not fool-proof!
You can achieve to this by making a Public property in your "settable class" that will inherit from the real class that will have a protected property... this way only the inherit class can SET and not class that doesn't inherit. But the drawback is that you will require to have an inherit class...
Reflection, though I would agree that having to do this just to get around an access modifier is probably an indication of a bad design.
public class Widget
{
private int count;
public int Count
{
get { return this.count; }
private set { this.count = value; }
}
}
public static class WidgetManager
{
public static void CatastrophicErrorResetWidgetCount( Widget widget )
{
Type type = widget.GetType();
PropertyInfo info = type.GetProperty("Count",BindingFlags.Instance|BindingFlags.NonPublic);
info.SetValue(widget,0,null);
}
}
The reason this is a design flaw is because it seems muddled between the scope of the two objects.
The properties of a class should be accessible in the context of that class, at least internally.
It sounds like the settable property on your item class is really a property of the manager class.
You could do something similar to what you want by closely coupling the two classes:
public class MyItem {
internal MyItemManager manager { get;set; }
public string Property1 {
get { return manager.GetPropertyForItem( this ); }
}
}
Unfortunately this isn't great design either.
What your looking for is what C++ calls a Friend class but neither c# or vb has this functionality. There is a lot of debate as to the merit of such functionality since it almost encourages very strong coupling between classes. The only way you could implement this in c# would be with reflection.
If your goal is to have a class Foo let some property (e.g. Bar, of type Biz) to be changed by some other object, without exposing it publicly, a simple way to do that is to have an instance of Foo which is supposed to be changeable by some other object to pass that other object an Action<Biz> which points to a private method that changes Bar to the passed-in value. The other object may use that delegate to change the Bar value of the object that supplied it.
If one wishes to have give all instances of some type Woozle the ability to set the Bar value of any instance of Foo, rather than exposing such abilities on a per-instance basis, one may require that Woozle have a public static method Woozle.InstallFooBarSetter which takes a parameter of type Action<Foo, Biz> and one of type Object. Foo should then have a static method WoozleRequestBarSetter which takes an Object, and passes it to Woozle.InstallFooBarSetter along with an Action<Foo,Biz>. The class initializer for Woozle should generate a new Object, and pass it to Foo.RequestBarSetter; that will pass the object to Woozle.InstallFooBarSetter along with a delegate. Woozle can then confirm that the passed-in object is the one that it generated, and--if so--install the appropriate delegate. Doing things this way will ensure that nobody but Woozle can get the delegate (since the delegate is only passed to Woozle.InstallFooBarSetter), and Woozle can be sure its delegate comes from Foo (since nobody else would have access to the object that Woozle created, and Woozle.InstallFooBarSetter won't do anything without it).
if it is a design flaw depends on what you want to do. You could use the StackTrace class from System.Diagnostics to get the Type of the class setting your property and then compare to the type you want to allow setting yor property..but maybe there are better ways for performing something like this (e.g. boxing)

Categories