How to delete object? - c#

I need to create a method of class that delete the instance.
public class Car
{
private string m_Color;
public string Color
{
get { return m_Color; }
set { m_Color = value; }
}
public Car()
{
}
public void Delete()
{
/*This method will delete the instance,
so any references to this instance will be now null*/
}
}
class Program
{
static void Main( string[] args )
{
Car car = new Car();
car.Delete();
if(car==null)
Console.WriteLine("It works.");
else
Console.WriteLine("It doesn't work.")
}
}
I want to know if there is any possible solution (even if it is not recommended) how to do this.
Instance of this class will be stored in hundreds of different class. I will try to describe this, for example there will be these classes:
public class CarKey
{
private Car m_Car;
public Car Car
{
get { return m_Car; }
}
public bool CarExist{ get{ return m_Car != null; } }
public CarKey( Car car )
{
m_Car = car;
}
}
public class Garages
{
private List<Car> m_Collection = new List<Car>();
private int m_Size;
public int Size{ get{ return m_Size; } }
public Garages( int size )
{
for(int i=0;i<size;i++)
m_Collection.Add(null);
}
public bool IsEmpty( int garage )
{
return m_Collection[garage] == null;
}
public void InsertCar( Car car, int garage )
{
if( m_Collection[garage] != null )
throw new Exception("This garage is full.");
m_Collection[garage] = car;
}
public Car GetCar( int garage )
{
if( m_Collection[garage] == null )
throw new Exception("There is no car, maybe it was deleted.");
return m_Collection[garage];
}
}

From any class you can't set its value to null. This is not allowed and doesn't make sense also -
public void Delete()
{
this = null; <-- NOT ALLOWED
}
You need an instance of class to call Delete() method so why not set that instance to null itself once you are done with it.
Car car = new Car();
// Use car objects and once done set back to null
car = null;
Anyhow what you are trying to achieve is not possible in C#. I suspect
from your question that you want this because there are memory leaks
present in your current design which doesn't let the Car instance to
go away. I would suggest you better profile your application and
identify the areas which is stopping GC to collect car instance and
work on improving that area.

I would suggest , to use .Net's IDisposable interface if your are thinking of to release instance after its usage.
See a sample implementation below.
public class Car : IDisposable
{
public void Dispose()
{
Dispose(true);
// any other managed resource cleanups you can do here
Gc.SuppressFinalize(this);
}
~Car() // finalizer
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
if (_stream != null) _stream.Dispose(); // say you have to dispose a stream
}
_stream = null;
_disposed = true;
}
}
}
Now in your code:
void main()
{
using(var car = new Car())
{
// do something with car
} // here dispose will automtically get called.
}

It sounds like you need to create a wrapper around an instance you can invalidate:
public class Ref<T> where T : class
{
private T instance;
public Ref(T instance)
{
this.instance = instance;
}
public static implicit operator Ref<T>(T inner)
{
return new Ref<T>(inner);
}
public void Delete()
{
this.instance = null;
}
public T Instance
{
get { return this.instance; }
}
}
and you can use it like:
Ref<Car> carRef = new Car();
carRef.Delete();
var car = carRef.Instance; //car is null
Be aware however that if any code saves the inner value in a variable, this will not be invalidated by calling Delete.

What you're asking is not possible. There is no mechanism in .Net that would set all references to some object to null.
And I think that the fact that you're trying to do this indicates some sort of design problem. You should probably think about the underlying problem and solve it in another way (the other answers here suggest some options).

You can proxyfy references to your object with, for example, dictionary singleton. You may store not object, but its ID or hash and access it trought the dictionary. Then when you need to remove the object you set value for its key to null.

You cannot delete an managed object in C# . That's why is called MANAGED language. So you don't have to troble yourself with delete (just like in c++).
It is true that you can set it's instance to null. But that is not going to help you that much because you have no control of your GC (Garbage collector) to delete some objects apart from Collect. And this is not what you want because this will delete all your collection from a generation.
So how is it done then ? So : GC searches periodically objects that are not used anymore and it deletes the object with an internal mechanism that should not concern you.
When you set an instance to null you just notify that your object has no referene anymore ant that could help CG to collect it faster !!!

Use a collection that is a static property of your Car class.
Every time you create a new instance of a Car, store the reference in this collection.
To destroy all Cars, just set all items to null.

FLCL's idea is very correct, I show you in a code:
public class O1<T> where T: class
{
public Guid Id { get; }
public O1(Guid id)
{
Id = id;
}
public bool IsNull => !GlobalHolder.Holder.ContainsKey(Id);
public T Val => GlobalHolder.Holder.ContainsKey(Id) ? (T)GlobalHolder.Holder[Id] : null;
}
public class GlobalHolder
{
public static readonly Dictionary<Guid, object> Holder = new Dictionary<Guid, object>();
public static O1<T> Instantiate<T>() where T: class, new()
{
var a = new T();
var nguid = Guid.NewGuid();
var b = new O1<T>(nguid);
Holder[nguid] = a;
return b;
}
public static void Destroy<T>(O1<T> obj) where T: class
{
Holder.Remove(obj.Id);
}
}
public class Animal
{
}
public class AnimalTest
{
public static void Test()
{
var tom = GlobalHolder.Instantiate<Animal>();
var duplicateTomReference = tom;
GlobalHolder.Destroy(tom);
Console.WriteLine($"{duplicateTomReference.IsNull}");
// prints true
}
}
Note: In this code sample, my naming convention comes from Unity.

You can use extension methods to achive this.
public static ObjRemoverExtension {
public static void DeleteObj<T>(this T obj) where T: new()
{
obj = null;
}
}
And then you just import it in a desired source file and use on any object. GC will collect it. Like this:Car.DeleteObj()
EDIT
Sorry didn't notice the method of class/all references part, but i'll leave it anyway.

Related

Implementing a safe access container

Assume I have some class that represents a container. That container holds some public properties with get and set modifiers.
What I want is to implement some mechanism that will enable access and disable access to these properties reference at runtime.
For example, when some boolean flag is true, you can access these properties. That means that:
SomeClass.Property1;
Will not generate an exception and will return the object.
However, when it is false, the above line of code will throw an exception.
It is of course possible to be done when using some boolean key, and checking it at the gateway to every property.
My question is, is it possible to implement such mechanism that will enfoce these limitations for all the properties in the class, without the need to assert these conditions within every access to these properties.
Thanks for helping.
It looks like null object pattern might helps.
Simple code that shows how it can be used in your case. Not exactly the same as you want but it doesn't need to assert conditions with every access to object's properties and methods.
Entities:
abstract class AbstractEntity
{
public abstract void DoSomething();
public abstract void DoSomethingElse();
public abstract int Property { get; set; }
}
class RealEntity : AbstractEntity
{
public override void DoSomething()
{
Console.WriteLine("Something");
}
public override void DoSomethingElse()
{
Console.WriteLine("Something else");
}
public override int Property { get; set; }
}
class NullEntity : AbstractEntity
{
public override void DoSomething()
{
// do nothing or throw exception
}
public override void DoSomethingElse()
{
// do nothing or throw exception
}
public override int Property
{
get { throw new Exception(); }
set { throw new Exception(); }
}
}
Simple example of AccessContainer:
class AccessContainer
{
private RealEntity _entity = new RealEntity();
private NullEntity _nullEntity = new NullEntity();
private bool _access = true;
public AbstractEntity Entity
{
get => _access ? (AbstractEntity) _entity : (AbstractEntity) _nullEntity;
}
public void OpenAccess()
{
_access = true;
}
public void DenyAccess()
{
_access = false;
}
}
Usage:
var container = new AccessContainer();
container.Entity.DoSomething(); // prints something
var prop = container.Entity.Property; // access to property
container.DenyAccess();
container.Entity.DoSomething(); // do nothing
container.OpenAccess();
container.Entity.DoSomething(); // prints something again
container.DenyAccess();
var prop2 = container.Entity.Property; // exception
What you are asking for doesn't natively exist, you're going to have to write some sort of wrapping functionality to test whether accessibility is granted.
public interface IAccessOwner {
bool Accessible { get; }
}
[DebuggerDisplay("Accessible: {Accessible,nq} - Value: {ToString()}")]
[DebuggerTypeProxy(typeof(RestrictedObject<>.DebuggerProxy))]
public class RestrictedObject<T> {
private readonly IAccessOwner _owner;
private T _value;
public RestrictedObject(IAccessOwner owner, T initialValue)
: this(owner) {
_value = initialValue;
}
public RestrictedObject(IAccessOwner owner) {
_owner = owner ?? throw new ArgumentNullException(nameof(owner));
}
public T Value {
get {
ThrowIfInaccessible();
return _value;
}
set {
ThrowIfInaccessible();
_value = value;
}
}
public bool Accessible => _owner.Accessible;
public override string ToString() {
if (!Accessible)
return "<Inaccessible>"; // ToString should never throw
if (_value is { } val)
return val.ToString();
return "<null>";
}
private void ThrowIfInaccessible() {
if(!Accessible)
throw new InvalidOperationException("Not accessible!");
}
// explicit operator to cast directly to value
public static explicit operator T(RestrictedObject<T> ro) {
ro.ThrowIfInaccessible();
return ro.Value;
}
private sealed class DebuggerProxy {
public bool Accessible { get; }
public T Value { get; }
public DebuggerProxy(RestrictedObject<T> ro) {
bool acc = Accessible = ro.Accessible;
if (acc)
Value = ro._value;
}
}
}
You can then use properties of this type in your class:
public class MyClass : IAccessOwner {
private readonly RestrictedObject<int> _prop1;
private readonly RestrictedObject<string> _prop2;
public MyClass(int someVal) {
_prop1 = new RestrictedObject<int>(this, someVal);
_prop2 = new RestrictedObject<string>(this);
Accessible = true;
}
public bool Accessible { get; private set; }
// you determine how you want to toggle the above property.
// Exposing it publicly defeats the purpose of all of this,
// but for demo purposes only:
public void DenyAccess() {
Accessible = false;
}
public void AllowAccess() {
Accessible = true;
}
// these properties will throw exceptions if the owner
// (this object) is not currently accessible.
public int Prop1 {
get => _prop1.Value;
set => _prop1.Value = value;
}
public string Prop2 {
get => _prop2.Value;
set => _prop2.Value = value;
}
// alternatively return the wrapper itself
// allowing you to control the accessibility
// even after returning the object
public RestrictedObject<string> AltProp2 => _prop2;
}
You would then use it like the following (obviously exceptions will halt the execution, handling has been elided):
var mc = new MyClass(3);
Console.WriteLine(mc.Prop1); // prints 3
Console.WriteLine(mc.Prop2); // prints null
var temp = mc.AltProp2; // use the wrapper directly
mc.Prop2 = "Hello";
Console.WriteLine(mc.Prop2); // prints Hello
Console.WriteLine(temp.Value); // prints Hello
Console.WriteLine((string)temp); // explicit operator, prints Hello
mc.DenyAccess();
mc.Prop1 = 33; // throws!
Console.WriteLine(mc.Prop1); // throws!
Console.WriteLine(mc.Prop2); // throws!
Console.WriteLine(temp.Value); // throws!
Console.WriteLine((string)temp); // explicit operator, throws!
Console.WriteLine(temp); // prints "<Inaccessible>"
mc.AllowAccess();
string temp3 = (string)temp; // "Hello", explicit operator works again
mc.Prop1 = 22; // as do our setters
mc.Prop2 = "Goodbye";
if (temp.Accessible) {
Console.WriteLine(temp); // "Goodbye"
}
The only thing that won't throw an exception is the override of ToString on the RestrictedObject type itself since you should never throw from ToString. Instead we just return <Inaccessible>.
We've also changed how the RestrictedObject<T> is displayed in a debugger via the DebuggerTypeProxyAttribute. If someone tries to inspect the object's properties they will see the Accessible property and only if true will the wrapped object's Value appear. Otherwise, default(T) will be displayed (null for reference types, 0 for integral types and false for bool). Furthermore, through use of the DebuggerDisplayAttribute we've customized the display of the collapsed version of our object such that it shows the Accessible property alongside our customized ToString.
Note that this still has the drawback that if someone retrieves the inner/wrapped object and accessibility has later been denied, they still have the object. There's nothing you are going to be able to do to really guard against that case. You must also realize (and accept) that anyone using reflection could alter or access the state of the object if they really wanted to.
I will also note that this violates normal C# practices, which typically dictate that properties should not throw exceptions. Microsoft's own guidelines say as much, though they use the term "Avoid" rather than "Do Not". The framework itself is guilty of violating this "rule". If you're going to violate the principle of least surprise, at the very least have the courtesy to document this behavior for consumers of your API.

Pass by Value in C#

How can I pass an object of a "MyClass" (C#) by Parameter-by-Value to a method? example:
MyClass obj = new MyClass();
MyClass.DontModify(obj); //Only use it!
Console.Writeline(obj.SomeIntProperty);
...
public static void DontModify(MyClass a)
{
a.SomeIntProperty+= 100;// Do something more meaningful here
return;
}
By default object types are passed by value in C#. But when you pass a object reference to a method, modifications in the object are persisted. If you want your object to be inmutable, you need to clone it.
In oder to do it, implement the ICloneable interface in your class. Here is a mock example of how to use ICloneable:
public class MyClass : ICloneable
{
private int myValue;
public MyClass(int val)
{
myValue = val;
}
public void object Clone()
{
return new MyClass(myValue);
}
}
By default, it is passed by value. However, you're passing the object reference by value, which means you can still edit values within the object.
In order to prevent the object from being able to change at all, you would need to actually clone the object prior to passing it into your method. This would require you to implement some method of creating a new instance that is a copy of your original object, and then passing in the copy.
public static void DontModify(MyClass a)
{
MyClass clone = (MyClass)a.Clone();
clone.SomeIntProperty+= 100;// Do something more meaningful here
return;
}
You could create a Clone method on your object to pass the return value to your method. C# cannot pass reference types by value so this might be a good alternative.
public MyClass CreateClone()
{
return new MyClass() { SomeIntProperty = this.SomeIntProperty };
}
class Program
{
static void Main(string[] args)
{
Person p1 = new Person()
{
Name = "Alsafoo",
Address = new Address()
{
City = "Chicago"
}
};
Person p2 = new Person(p1.Address);
p2 = p1.GetClone(CloningFlags.Shallow);
p2.Name = "Ahmed";
p2.Address = new Address(){City = "Las Vegas"};
Console.WriteLine("p1 first name: {1} --- p1 city: {2} {0}p2 first name: {3} ---- p2 city: {4}",
Environment.NewLine, p1.Name, p1.Address.City, p2.Name, p2.Address.City);
Console.ReadKey();
}
}
public class Person
{
public Person()
{}
public Person(Address a)
{
Address = a;
}
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string City { get; set; }
}
Download this extension
https://www.nuget.org/packages/CloneExtensions/1.2.0
Created a Extention method
using System.Text.Json;
namespace Student.Utilities
{
public static class CloneExtension
{
public static T Clone<T>(this T cloneable) where T : new()
{
var toJson = JsonSerializer.Serialize(cloneable);
return JsonSerializer.Deserialize<T>(toJson);
}
}
}
Now, while calling, call it like this to pass the clone to another method:
public void CreateStudent(Student student)
{
Student clonedStudent = student.Clone<Student>();
_repository.CreateStudent(clonedStudent);
}

Object Oriented Programming Nth Child

language specific (however, if you need a language please use C++/C# or Javascript). I trying to figure out how I would go about doing this, and how I would access the child objects from a parent object.
Say I have the following classes, and these are not written properly etc... :
Class: roomContainer (container of objects)
Class: Table (base class for a table, contains property of maximum-seats, current-number-of-seats, array of seats )
Class: Desk (extends Table, contains property for maximum draws, array of draws )
Class: seat (base class for seats, contains property of maximum-legs, arm-rest, back-rest)
Class: couch (extends seat, adds property maximum seats)
If I create an instance of roomContainer, and add within it's container a table, couch. Within the table I create multiple seats (or chairs), and a desk.
How would I be able to access the property of child objects property, when the parent has a container of different objects. I.e the roomContainer Container of objects, one of them is a table, and a desk - where the desk has different properties and an array of draws etc.. ?
You're looking for something called the Composite Design Pattern. This allows you to nest objects (as you described), and hold references to both the parent and the children (though some implementations do no maintain a parent reference - this is optional).
Here is an example implementation using your schema:
public static class Program // the supporting class definitions are below
{
public static void Main()
{
// create a root container
var room = new RoomContainer();
// create a child
var table = new Table(room, 4);
// put the table in the room
room.Add(table);
MakeMess(room);
}
// to show you how to access the properties
// if you don't already have a reference:
public static void MakeMess(RoomContainer room)
{
if(room == null)
{
throw new ArgumentNullException("room");
}
var seats = room.GetChildren<Table>().First().Seats.ToArray();
for (int index = 0; index < seats.Length; index++)
{
Console.WriteLine("You have kicked over Seat #{0}",(index+1).ToString());
}
}
}
// This is the base class of the components and provides the core functionality.
// You will want to make this object's interface minimal, so that the logic
// is consistent with all its children (without knowing what they might be in advance)
public abstract class Component
{
private readonly IList<Component> _children;
private readonly Component _container;
protected Component(Component container)
{
_container = container;
_children = new Component[] { };
}
public bool IsRoot { get { return _container == null; } }
public abstract bool IsContainer { get; }
public virtual void Add(Component component)
{
if (component == null)
{
throw new ArgumentNullException("component");
}
if (!IsContainer)
{
throw new NotSupportedException("Add is not supported by leaf components");
}
_children.Add(component);
}
public IEnumerable<T> GetChildren<T>()
where T: Component
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children.OfType<T>();
}
public IEnumerable<Component> Children
{
get
{
if (!IsContainer)
{
throw new NotSupportedException("Only containers have children");
}
return _children;
}
}
}
public class RoomContainer : Component
{
public RoomContainer() : base(null)
{
}
public override bool IsContainer { get { return true; } }
}
public class Table : Component
{
private readonly int _maximumSeatCount;
public Table(Component container, int maximumSeatCount) : base(container)
{
_maximumSeatCount = maximumSeatCount;
}
public override bool IsContainer { get { return true; } }
protected virtual bool CanAdd(Component component)
{
return component is Seat && MaximumSeatCount > CurrentSeatCount;
}
public override void Add(Component component){
if(CanAdd(component)){
base.Add(component);
}
else
{
throw new NotSupportedException("The component was an invalid child of Table and could not be added.");
}
}
public int MaximumSeatCount { get { return _maximumSeatCount; } }
public int CurrentSeatCount { get { return Seats.Count(); } }
public IEnumerable<Seat> Seats { get { return Children.OfType<Seat>(); } }
}
public class Seat : Component
{
// you can restrict the constructor to only accept a valid parent
public Seat(Table table) : base(table)
{
}
public override bool IsContainer
{
get { return false; }
}
}
If the all share common methods, for example Render(), Update(), SaveDetails(int Id), LoadDetails(int Id) then you could make them all inherit from a base class, or all impliment a common interface. This would remove the need for casting (below) when calling a common method (or accessing a common property).
To access properties unique to the derived class you would check the type of the child object, then cast the child object to access the property.
EDIT: Example:
foreach(Object obj in Room.ChildObjects)
{
if(obj is Desk)
{
Desk DeskObj = obj as Desk; // Cast the object reference as a desk.
DeskObj.MaxDraws = 50; // It's a big desk!
DestObj.Draws[1] = new Draw(); // ......
}
}
Something like this:
IEnumerable<Desk> desks = roomContainer.OfType<Desk>();
//Iterate and do stuff.
IEnumerable<Table> tables = roomContainer.OfType<Table>();
//Iterate and do stuff.

Inheriting an already instantiated base object

Is it possible to do something like the following:
public class ChildClass : BaseClass
{
public ChildClass(BaseClass o)
{
base = o;
}
}
Basically, I want a transparent way to wrap a base class inside of other functionality. One example I've thought of is a custom Settings Provider which transparently audits the settings passed through it.
public class SettingsAuditor : SettingsProvider
{
public SettingsAuditor(SettingsProvider o)
{
base = o;
}
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
base.SetPropertyValues(context, propvals);
}
}
Then I could do the following:
mySettingsProvider = new SettingsAuditor(mySettingsProvider);
And all changes would go through the overridden SetPropertyValues before passing to the original object.
I could use a private SettingsProvider member, but then I either cannot inherit from SettingsProvider, or have an entire SettingsProvider (base) not being used at all.
I'm using C# 4.0 and .Net 4.0.
You cannot do base = o;
What you're looking for is the Decorator Pattern), which is a way to compositionally add functionality at runtime (vs. inheritance).
Instead of trying to set the base, you just contain the inner member. As long as the wrapper implements the same interface or base class as the inner object, you can pass back the new wrapper. You can wrap as many decorators as you want.
Consider:
public interface ICar
{
void Drive();
}
public class Car : ICar
{
public void Drive()
{
Console.WriteLine("vroom");
}
}
public class BuckleUp : ICar
{
ICar car;
public BuckleUp(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("click!");
car.Drive();
}
}
public class CheckMirrors : ICar
{
ICar car;
public CheckMirrors(ICar car) { this.car = car; }
public void Drive()
{
Console.WriteLine("mirrors adjusted");
car.Drive();
}
}
Now consider you have a method that accepts an ICar and tells it to drive. You could give it a Car, and it would work, but you could also wrap that car in a BuckleUp and a CheckMirrors and you wouldn't have to change that method at all. You've modified functionality through composition using the Decorator Pattern.
No. This looks like it should be a Composition vs Inheritance issue. You need to evaluate whether you are a "is a" or a "has a."
A little help for your journey
This is not a complete implmentation and it could probably be done much cleaner with expression trees... but this was a quick swing at faking AOP using DynamicObject with .Net 4.0.
public class MyDynamicWrapper<T> : DynamicObject
{
public T Wrapped { get; private set; }
public Action<T> Pre { get; private set; }
public Action<T> Post { get; private set; }
public MyDynamicWrapper(T wrapped, Action<T> pre, Action<T> post)
{
this.Wrapped = wrapped;
this.Pre = pre;
this.Post = post;
}
public override bool TryGetMember(
GetMemberBinder binder,
out object result)
{
var type = typeof(T);
var method = type.GetMethod(binder.Name);
if (method != null)
{
Func<object> func = () =>
{
if (Pre != null)
Pre(Wrapped);
// support for input parameters could be added here
var ret = method.Invoke(Wrapped, null);
if (Post != null)
Post(Wrapped);
return ret;
};
result = func;
return true;
}
return base.TryGetMember(binder, out result);
}
}
public class MyDynamicWrapper
{
public static MyDynamicWrapper<T> Create<T>(
T toWrap,
Action<T> pre = null,
Action<T> post = null)
{
return new MyDynamicWrapper<T>(toWrap, pre, post);
}
}
public class MyObject
{
public void MyMethod()
{
Console.WriteLine("Do Something");
}
}
class Program
{
static void Main()
{
var myobject = new MyObject();
dynamic mydyn = MyDynamicWrapper.Create(
myobject,
p => Console.WriteLine("before"),
p => Console.WriteLine("after"));
// Note that you have no intellisence...
// but you could use the old implmentation before you
// changed to this wrapped version.
mydyn.MyMethod();
/* output below
before
Do Something
after
*/
}
}
No, but you could fake it:
public class SettingsAuditor
{
SettingsProvider #base;
public SettingsAuditor(SettingsProvider o)
{
#base = o;
}
public void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propvals)
{
// Log the property change to a file
#base.SetPropertyValues(context, propvals);
}
}
Note here, #base isn't the actual base, just a varaible named base

How to change the class of an object dynamically in C#?

Suppose I have a base class named Visitor, and it has 2 subclass Subscriber and NonSubscriber.
At first a visitor is start off from a NonSubscriber, i.e.
NonSubscriber mary = new NonSubscriber();
Then later on this "mary" subscribed to some services, and I want to change the type of "mary" to Subscriber.
What is the conventional way to do that?
can't do that. sorry. C# is not a dynamic language.
You will have to create a new mary = new Subscriber(); and copy all relevant properties.
But a better approach might be to model it differently: Give Visitor a list of subscriptions. An empty list means a NonSubscriber.
You cant do this type of conversion.
What you should do is treat mary as a visitor, and when time arrives, create a new instance of "subscriber":
Visitor mary = new NonSubscriber();
// Do some Visitor operations
...
// Now mary is a Subscriber
mary = new Subscriber();
You could use the GOF design patterns State or Strategy to model such an behaviour. Using these patterns, it seems during runtime as if the class of the objects has been changed.
It seems that you have some design problems. I think that it would be better to redesign your code like:
class Visitor
{
private bool isSubscriber = false;
public bool IsSubscriber
{
get { return isSubscriber; }
}
public void Subscribe()
{
// do some subscribing stuff
isSubscriber = true;
}
public void Unsubscribe()
{
// do some unsubscribing stuff
isSubscriber = false;
}
}
You cannot change the type of a variable at runtime. You need to create a new instance.
mary = new Subscriber();
Create a Subscriber constructor that takes a NonSubscriber object as a parameter, or create a method on the NonSubscriber object that returns a Subscriber to save you having to writer the mappping code in multiple places.
It seems like you are encoding information incorrectly into your class hierarchy. It would make more sense to use a different pattern than sub classing here. For example, use only one class (visitor, or perhaps you could name it potential subscriber, whatever seems appropriate) and encode information on the services the object is subscribed to, moving the dynamically changing behavior behind a "Strategy" pattern or some such. There's very little detail in your example, but one thing you could do in C# is to make a "subscriber" property which would change the behavior of the object when the state of the property was changed.
Here's a contrived somewhat related example:
class Price
{
private int priceInCents;
private bool displayCents;
private Func<string> displayFunction;
public Price(int dollars, int cents)
{
priceInCents = dollars*100 + cents;
DisplayCents = true;
}
public bool DisplayCents
{
get { return displayCents; }
set
{
displayCents = value;
if (displayCents)
{
this.displayFunction = () => String.Format("{0}.{1}", priceInCents / 100, priceInCents % 100);
}
else
{
this.displayFunction = () => (priceInCents / 100).ToString();
}
}
}
public string ToString()
{
return this.displayFunction();
}
}
public class User
{
public Subscription Subscription { get; set; }
public void HandleSubscription()
{
Subscription.Method();
}
}
public abstract class SubscriptionType
{
public abstract void Method();
}
public class NoSubscription : SubscriptionType
{
public override void Method()
{
// Do stuff for non subscribers
}
}
public class ServiceSubscription : SubscriptionType
{
public override void Method()
{
// Do stuff for service subscribers
}
}
public class Service2Subscription : SubscriptionType
{
public override void Method()
{
// Do stuff for service2 subscribers
}
}
Think the code explains my answer :)
Adding to the other answers and your comment, you indeed can use the state pattern for your purpose, it would go something like this:
public class MyProgram
{
public void Run()
{
Visitor v = new Visitor("Mary");
Debug.Assert(v.SubscriptionLinkText == "Join now");
v.IsSubscribed = true;
Debug.Assert(v.SubscriptionLinkText == "Today's special");
v.IsSubscribed = false;
Debug.Assert(v.SubscriptionLinkText == "Join now");
}
}
public class Visitor
{
public string Name { get; set; }
private bool _isSubscribed;
public bool IsSubscribed
{
get { return this._isSubscribed; }
set
{
if (value != this._isSubscribed)
{
this._isSubscribed = value;
this.OnSubscriptionChanged();
}
}
}
private SubscriptionBase _subscription;
public string SubscriptionLinkText
{
get { return this._subscription.LinkText; }
}
public Visitor(string name)
{
this.Name = name;
this._isSubscribed = false;
this.OnSubscriptionChanged();
}
private void OnSubscriptionChanged()
{
// Consider also defining an event and raising it here
this._subscription =
SubscriptionBase.GetSubscription(this.IsSubscribed);
}
}
abstract public class SubscriptionBase
{
// Factory method to get instance
static public SubscriptionBase GetSubscription(bool isSubscribed)
{
return isSubscribed ?
new Subscription() as SubscriptionBase
: new NoSubscription() as SubscriptionBase;
}
abstract public string LinkText { get; }
}
public class Subscription : SubscriptionBase
{
public override string LinkText
{
get { return "Today's Special"; }
}
}
public class NoSubscription : SubscriptionBase
{
public override string LinkText
{
get { return "Join now"; }
}
}

Categories

Resources