Background
I want to allow a class instance to register callbacks with an event system while avoiding boxing.
A bit of background: I have a home-grown Event System structured as shown below:
class EventSystem
{
// registers a struct instance with an event
// when the event triggers, it calls the run() method and passes in some info
public void Register(ICallback callbackStruct, Event e);
}
public enum Event
{
SOME_EVENT,
SOME_OTHER_EVENT
}
interface ICallback
{
void Run(string data);
}
An example implementation of this is:
class Example
{
private Behaviour_A a = new Behaviour_A();
private Behaviour_B b = new Behaviour_B();
public Example()
{
eventSystem.Register(a, SOME_EVENT);
eventSystem.Register(b, SOME_OTHER_EVENT);
}
struct Behaviour_A : ICallback
{
void Run(string data)
{
// some behvaiour
}
}
struct Behaviour_B : ICallback
{
void Run(string data)
{
// some other behvaiour
}
}
}
Pros
I like this solution because it makes use of composition rather than inheritance (and also supports multiple callback behaviours for the same event in one instance), and I'd prefer to use structs over anonymous functions since they are stateful and might be re-used with different parameters and a few other reasons.
Cons
However, I dislike this solution because it requires boxing each time the struct is passed around and I'm trying to avoid heap allocations as much as possible.
Question
Is there any way I can implement custom behaviouron a struct as shown while avoiding boxing?
The key to avoiding boxing when using structs that implement interfaces is to use interface-constrained generics.
If one has a function that receives an argument of type T, where T is constrained to IEquatable<T>, then the .NET runtime will generate a separate machine code version of that function for every distinct structure type that is passed to it, and within those machine-code versions of the function no boxing will be required.
It's not a answer but just a suggestion . Decoupling Data and Behaviour , it's more clean design. and make sure Register param is a class. this way is good to handle boxing by you self. maybe use object pool or something. This way can handle unnecessary GC.
public class EventSystem
{
// here make sure T is a class , not struct.
public void Register<T>(T callbackStruct, Event e) where T : class , ICallback
{
}
}
public enum Event
{
SOME_EVENT,
SOME_OTHER_EVENT
}
public interface ICallback
{
void Run(string data);
}
class Example
{
private Behaviour_A a = new Behaviour_A();
private Behaviour_B b = new Behaviour_B();
public Example()
{
EventSystem eventSystem = new EventSystem();
staticAObj.PutData(a);
eventSystem.Register(staticAObj, Event.SOME_EVENT);
eventSystem.Register(b, Event.SOME_OTHER_EVENT);
}
struct A
{
}
struct B
{
}
class Behaviour_A : ICallback
{
A a;
public void Run(string data)
{
// some behvaiour
}
}
class Behaviour_B : ICallback
{
B b;
public void Run(string data)
{
// some other behvaiour
}
}
}
Unless I missed something obvious, your registration method should just add the ref modifier:
public void Register(ref ICallback callbackStruct, Event e);
This guarantees your structure will not be copied on the stack because only the reference will be copied, and your original struct can be used through that. The heap remains intact.
You will have to modify the callsite:
eventSystem.Register(ref a, SOME_EVENT);
eventSystem.Register(ref b, SOME_OTHER_EVENT);
And, based on Guru's comments, this might be a solution: further modify the signature to
void Register<T>(ref T callbackStruct, Event e) where T : ICallback;
or
void Register<T>(ref T callbackStruct, Event e) where T : struct, ICallback;
to remove the box, but you're possibly adding brittleness to this code.
For yourEventSystem to register this it would need to be either non-abstract and provide the method below, or it would need a subclass that implements
public void Register<T>(ref T callbackStruct, Event e) where T : struct, ICallback
{}
Related
I have a Holder class that is passed Instructions. I want other classes to be able to register delegates with the holder so that when a certain type of Instruction is passed to it, the delegate gets executed. What's the right way to implement this?
I feel like there's some common design pattern, possibly involving EventHandler, but I'm not sure what it is. I'm trying to avoid making the delegate functions accept Instruction and then the first line of the function is always casting it to the correct derived type.
Here is a non-working example of what I want, two classes registering their functions with the types they care about. It doesn't compile because I'm trying to add a delegate that accepts a derived type where the dictionary value is for delegates that accept the parent type.
abstract class Instruction { }
class InstructionA : Instruction { }
class InstructionB : Instruction { }
// I want this to accept the relevant derived class instead of Instruction.
delegate void InstructionDelegate(Instruction instruction);
class Holder {
public Dictionary<Type, List<InstructionDelegate>> delegateLists = new Dictionary<Type, List<InstructionDelegate>>();
public void ProcessInstruction(Instruction instruction) {
foreach (var f in delegateLists[typeof(Instruction)]) {
f(instruction);
}
}
}
class SomeClass {
SomeClass(Holder holder) {
holder.delegateLists[typeof(InstructionA)].Add(HandleInstructionA); // doesn't compile
}
void HandleInstructionA(InstructionA a) { }
}
class OtherClass {
OtherClass(Holder holder) {
holder.delegateLists[typeof(InstructionA)].Add(HandleInstructionA); // doesn't compile
holder.delegateLists[typeof(InstructionB)].Add(HandleInstructionB); // doesn't compile
}
void HandleInstructionA(InstructionA a) { }
void HandleInstructionB(InstructionB b) { }
}
I think my question is best descirbed by a code snippet:
class A
{
public void FunctionToBeCalled();
}
class B
{
public void FunctionToBeCalledAfter();
}
Now, after a FunctionToBeCalledAfter() call, FunctionToBeCalled() needs to "know" it must be called. B cannot have an A member, but A can have a B member. Is there any way this can be implemented in C#?
Why i need this:
Class A is Application level on OSI stack. Classes B and C(unmentioned before) are Transport Level. C makes calls to FunctionToBeCalledAfter, and after this FunctionToBeCalled needs to be called. But sincer A is a higher level, B and C cannot depend(have a member A), i don't know how to call FunctionToBeCalled.
I see 2 ways to accomplish this, one easier but (arguably) less elegant, one a little more involved but (arguably) more elegant
The less elegant solution: Singleton
A Singleton pattern enforces that there can only ever be one instance of a class at any given time, this seems to line up with your description of A (which from here on out I'll call Foo, and I'll be calling B Bar). So let's implement it:
public class Foo
{
private static Foo _instance;
public static Foo Instance => _instance ?? (_instance = new Foo());
// Private constructor so no one else can instantiate Foo
private Foo() { }
public void FunctionToBeCalled() { /* your code here */ }
}
public class Bar
{
public void FunctionToBeCalledAfter()
{
// Your existing code here
Foo.Instance.FunctionToBeCalled();
}
}
Now, the problem here is if your requirements ever change and you need multiple Foos, that'll be quite a refactor to implement it. Another (larger) downside is that we explicitly reference (i.e depend on) Foo, which isn't great and a problem if Bar is inside a project/ library that cannot directly reference Foo. Luckily solution 2 fixes those problems:
The more elegant solution: Events
public class Foo
{
// We don't need Foo to be a singleton anymore
public void FunctionToBeCalled() { /* Your code here */ }
}
public class Bar
{
public delegate void FunctionToBeCalledAfterEventHandler();
public event FunctionToBecalledAfterEventHandler FunctionToBeCalledAfterEvent;
public void FunctionToBeCalledAfter()
{
// Your existing code here
OnFunctionToBeCalledAfterEvent(); // Fire the event
}
private void OnFunctionToBeCalledAfterEvent()
{
FunctionToBeCalledEvent?.Invoke();
}
}
Now, everywhere where you're creating an instance of Bar you need to have a reference to Foo and subscribe to the event like so:
// foo = instance of class Foo
var bar = new Bar();
// The compiler is smart enough to find out that 'FunctionToBeCalledAfterEvent'
// has the same signature as 'FunctionToBeCalledAfterEvent' and can call it directly
// If this just so happens to not be case, see second way to subscribe to events
bar.FunctionToBeCalledAfterEvent += foo.FunctionToBeCalled;
// Or
bar.FunctionToBeCalledAfterEvent += () => foo.FunctionToBeCalled();
Events are great
Class B can have an event that other parties can handle. At the end of B.FunctionToBeCalledAfter this event would be invoked. Anyone who registered for this event would then be notified. Usual boilerplate code involves one virtual method that invokes one event. It's the standard way of adding events. If there is no need for additional data in the event then EventArgs is used. If additional data is needed then you could replace EventArgs with EventArgs<YourData>, or as an alternative, introduce a class XxxArgs derived from EventArgs with this additional data.
Class B
{
public event EventHandler FinishedFunctionToBeCalledAfter;
protected virtual void OnFinishedFunctionToBeCalledAfter(EventArgs e)
{
EventHandler handler = FinishedFunctionToBeCalledAfter;
handler?.Invoke(this, e);
}
public void FunctionToBeCalledAfter()
{
...
OnFinishedFunctionToBeCalledAfter(EventArgs.Empty);
}
}
Now when class A gets a hold of an object of class B it would add its event handler to it:
class A
{
public void FunctionToBeCalled();
public void FinishedFunctionToBeCalledAfter(object source, EventArgs e);
public void IntroduceObject(B b)
{
b.FinishedFunctionToBeCalledAfter += FinishedFunctionToBeCalledAfter;
}
}
When this object b of class B should end its life class A must know about it so that it can remove its event handler:
b.FinishedFunctionToBeCalledAfter -= FinishedFunctionToBeCalledAfter;
I want a particular method in one class to only be accessible by a particular class. For example:
public class A
{
public void LimitedAccess() {}
public void FullAccess() {}
}
public class B
{
public void Func()
{
A a = new A();
a.LimitedAccess(); // want to be able to call this only from class B
}
}
public class C
{
public void Func()
{
A a = new A();
a.FullAccess(); // want to be able to call this method
a.LimitedAccess(); // but want this to fail compile
}
}
Is there is a keyword or attribute that I can use to enforce this?
UPDATE:
Due to existing system complexity and time constraints, I needed a low impact solution. And I wanted something to indicate at compile time that LimitedAccess() could not be used. I trust Jon Skeet's answer that exactly what I had asked for could not be done in C#.
The question and Jon's answer are good for those who may run across this later. And the fact that this design smells can hopefully veer anyone away for choosing something like this as a desired a solution.
As mentioned in a comment, the C# friend conversation is useful reading if you are trying to solve a similar situation.
As for my particular solution: "why would A contain B's logic" (asked by #sysexpand in comments). That's the rub. B.Func() was called throughout the system I'm working on, but it primarily operated on a singleton of A. So what I ended up doing was moving B's Func() into A and making A.LimitedAccess() private. There were a few other details to work around, as there always are, but I got a low impact solution that gave me compile-time errors on callers to A.LimitedAccess().
Thanks for the discussion.
No. The only thing you could do would be to make LimitedAccess a private method, and nest class B within class A.
(I'm assuming you want all the classes in the same assembly. Otherwise you could put A and B in the same assembly, and C in a different assembly, and make LimitedAccess an internal method.)
Yes. What you are asking for is perfectly possible.
You can restrict access to methods and variables for a specific instance, by using an interface.
However, an interface alone cannot prevent someone from creating their own instance of the class, at which point they will have full access to that instance.
To do that, next you should nest it as a private class inside of another class in order to restrict access to the constructor.
Now you have a particular method in one class to only be accessible by a particular class.
In this example, only class B is ever able to access function LimitedAccess.
public interface IA
{
void FullAccess();
}
public class B
{
private class A : IA
{
public void LimitedAccess() {} //does not implement any interface
public void FullAccess() {} //implements interface
}
private A a = new A();
public IA GetA()
{
return (IA)a;
}
public void Func()
{
/* will be able to call LimitedAccess only from class B,
as long as everybody else only has a reference to the interface (IA). */
a.LimitedAccess();
}
}
//This represents all other classes
public class C
{
public void Func(IA ia)
{
ia.FullAccess(); // will be able to call this method
ia.LimitedAccess(); // this will fail to compile
}
}
public static class MainClass
{
public static void Main(string[] args)
{
B b = new B();
b.Func();
IA ia = b.GetA();
C c = new C();
c.Func(ia);
}
}
In case you just want to remind yourself (or team mates) to not call LimitedAccess everywhere, you could consider using explicit interface implementation or mark LimitedAccess as obsolete.
public interface IA
{
void LimitedAccess();
void FullAccess();
}
public class A : IA
{
private void LimitedAccess() { }
public void FullAccess() { }
void IA.LimitedAccess() => LimitedAccess();
void IA.FullAccess() => FullAccess();
}
public class B
{
public void Func()
{
IA a = new A();
a.LimitedAccess(); // want to be able to call this only from class B
}
}
public class C
{
public void Func()
{
A a = new A();
a.FullAccess(); // want to be able to call this method
a.LimitedAccess(); // -> fails to compile
}
}
Maybe this is a workaround.
Use the System.Runtime.CompilerServices and then you can either check the Name of the calling function and/or the file, in which the calling function is defined. If you have a class per file, the filename might be a substitude for the class name. Check it and block the call.
internal void MySecretFunction (string something,
[CallerMemberName] string memberName = null,
[CallerFilePath] string filePath = null,
[CallerLineNumber] int lineNumber = 0) {
if (!filePath.EndsWith(#"\goodClass.cs")) return;
// else do something
}
You could always see the calling type with a StackTrace.
Just note that when building in release mode, the call on the stack will get optimized, and its possible that the stack trace could return a completely different class, so just make sure to test it before you publish.
/// <summary>
/// Warning: Any class that calls this other than "B" will throw an exception.
/// </summary>
public void LimitedAccess()
{
if (new System.Diagnostics.StackTrace().GetFrame(1).GetMethod().DeclaringType != typeof(B)) throw new Exception("Invalid Caller Type, B is only class able to call this method.");
}
Unfortunately you wont be able to know if its an error on compile time. Best you can do is throw an exception if it gets called, and add a comment warning people about it.
It is against OOP best practices to make such a design. Methods of classes are not supposed to be protected from being called.
If your design requires control over calling a method, then control should be exercised by testing the arguments - caller which is authorized to make a call would "know" the magic word to pass as the argument.
This is a variation of the solution suggested by #cowlinator using class AWithUnlimitedAccess derived from class A rather than class A implementing interface IA.
The result and the limitations are the same, but I like it better because (1) the limited access methods are defined inside its own class and (2) it's easier to add documentation comments.
public class A
{
public void FullAccess() { }
}
public class AWithUnlimitedAccess : A
{
public void LimitedAccess() { }
}
public class B
{
private AWithUnlimitedAccess a = new AWithUnlimitedAccess();
public A GetA()
{
return a;
}
public void Func()
{
a.FullAccess();
a.LimitedAccess();
}
}
// This represents all other classes
public class C
{
public A A;
public void Func()
{
A.FullAccess();
A.LimitedAccess(); // this will fail compile
}
}
public static class MainClass
{
static void Main(string[] args)
{
B b = new B();
b.Func();
C c = new C();
c.A = b.GetA();
c.Func();
}
}
(Language is c# with VS 2008)
I have the following problem:
There are a number of structs (provided as is from 3rd party) that all implement certain methods with the same signatures.
I would like to wrap these struct with wrapper classes that implement a certain interface so that these classes can be treated in a uniform way.
Example:
interface AnInterface
{
void DoSomething();
}
struct Struct1
{
public void DoSomething();
}
class Struct1Wrapper : AnInterface
{
private Struct1 m_struct;
public override void DoSomething() // AnInterface implementation
{
m_struct.DoSomething();
}
}
Note that Struct1 DoSomething method is concrete while Struct1Wrapper implements it through an interface for easier handling.
The same goes with Struct2 and so on - the code of StructXWrapper is the same except for Struct1 replaced by StructX
I have tried using generics in order to avoid code duplication:
class GenericStructWrapper<AStruct> : AnInterface
{
private AStruct m_struct;
public override void DoSomething() // AnInterface implementation
{
m_struct.DoSomething();
}
}
But this won't work since the compiler doesn't have a notion about AStruct DoSomething() method.
Any other idea how to implement this without duplicating the code of Struct1Wrapper?
Perhaps there is some macro-like feature or some use of reflection?
Thanks,
Ury Jamshy.
You can take a Action<AStruct> in the class constructor that takes the method.
You can then create instances like new GenericStructWrapper<Struct1>(s => s.DoSomething())
C# doesn't safely support structural typing (except in certain unusual contexts), so there's no way to make this completely safe without code-duplication. You either have to go with SLak's technique of asking the client to provide a delegate (will probably involve repeating the same lambda expression over and over) or to assume that the underlying types will satisfy the contract of containing a public void DoSomething() method.
Going with the second option, here's one way using dynamic in C# 4:
public class StructWrapper: AnInterface
{
private readonly dynamic m_struct;
public StructWrapper(object myStruct)
{
m_struct = myStruct;
}
public void DoSomething()
{
m_struct.DoSomething();
}
}
Now, you could try to make this class generic, with the underlying-structure type being the generic-type argument, but that will probably not help you all that much unless you also want to perform structure-specific operations on the wrapped-type. Here's an example of that, with reflection and delegates (C# 3 compatible):
public class StructWrapper<T> : AnInterface where T : struct
{
private readonly Action action;
// deliberately exposed
public T UnderlyingStruct { get; private set; }
public StructWrapper(T underlyingStruct)
{
UnderlyingStruct = underlyingStruct;
action = (Action)Delegate.CreateDelegate
(typeof(Action), underlyingStruct, "DoSomething");
}
public void DoSomething()
{
action();
}
}
Note that you can mix and match the two techniques mentioned above, e.g. reflection but without generics.
Usage:
AnInterface wrapper1 = new StructWrapper(new Struct1());
wrapper1.DoSomething();
StructWrapper<Struct1> wrapper2 = new StructWrapper<Struct1>(new Struct1());
wrapper2.DoSomething();
Struct1 s = wrapper2.UnderlyingStruct; // generics help here
s.SomeOtherMethod();
There is a syntax for this:
class GenericStructWrapper<AStruct> : AnInterface where AStruct : AnInterface
{
private AStruct m_struct;
public override void DoSomething() // AnInterface implementation
{
m_struct.DoSomething();
}
}
This says that AStruct must implement AnInterface
What is the best way to implement polymorphic behavior in classes that I can't modify? I currently have some code like:
if(obj is ClassA) {
// ...
} else if(obj is ClassB) {
// ...
} else if ...
The obvious answer is to add a virtual method to the base class, but unfortunately the code is in a different assembly and I can't modify it. Is there a better way to handle this than the ugly and slow code above?
Hmmm... seems more suited to Adapter.
public interface ITheInterfaceYouNeed
{
void DoWhatYouWant();
}
public class MyA : ITheInterfaceYouNeed
{
protected ClassA _actualA;
public MyA( ClassA actualA )
{
_actualA = actualA;
}
public void DoWhatYouWant()
{
_actualA.DoWhatADoes();
}
}
public class MyB : ITheInterfaceYouNeed
{
protected ClassB _actualB;
public MyB( ClassB actualB )
{
_actualB = actualB;
}
public void DoWhatYouWant()
{
_actualB.DoWhatBDoes();
}
}
Seems like a lot of code, but it will make the client code a lot closer to what you want. Plus it'll give you a chance to think about what interface you're actually using.
Check out the Visitor pattern. This lets you come close to adding virtual methods to a class without changing the class. You need to use an extension method with a dynamic cast if the base class you're working with doesn't have a Visit method. Here's some sample code:
public class Main
{
public static void Example()
{
Base a = new GirlChild();
var v = new Visitor();
a.Visit(v);
}
}
static class Ext
{
public static void Visit(this object b, Visitor v)
{
((dynamic)v).Visit((dynamic)b);
}
}
public class Visitor
{
public void Visit(Base b)
{
throw new NotImplementedException();
}
public void Visit(BoyChild b)
{
Console.WriteLine("It's a boy!");
}
public void Visit(GirlChild g)
{
Console.WriteLine("It's a girl!");
}
}
//Below this line are the classes you don't have to change.
public class Base
{
}
public class BoyChild : Base
{
}
public class GirlChild : Base
{
}
I would say that the standard approach here is to wrap the class you want to "inherit" as a protected instance variable and then emulate all the non-private members (method/properties/events/etc.) of the wrapped class in your container class. You can then mark this class and its appropiate members as virtual so that you can use standard polymorphism features with it.
Here's an example of what I mean. ClosedClass is the class contained in the assembly whose code to which you have no access.
public virtual class WrapperClass : IClosedClassInterface1, IClosedClassInterface2
{
protected ClosedClass object;
public ClosedClass()
{
object = new ClosedClass();
}
public void Method1()
{
object.Method1();
}
public void Method2()
{
object.Method2();
}
}
If whatever assembly you are referencing were designed well, then all the types/members that you might ever want to access would be marked appropiately (abstract, virtual, sealed), but indeed this is unfortunately not the case (sometimes you can even experienced this issue with the Base Class Library). In my opinion, the wrapper class is the way to go here. It does have its benefits (even when the class from which you want to derive is inheritable), namely removing/changing the modifier of methods you don't want the user of your class to have access to. The ReadOnlyCollection<T> in the BCL is a pretty good example of this.
Take a look at the Decorator pattern. Noldorin actually explained it without giving the name of the pattern.
Decorator is the way of extending behavior without inheriting. The only thing I would change in Noldorin's code is the fact that the constructor should receive an instance of the object you are decorating.
Extension methods provide an easy way to add additional method signatures to existing classes. This requires the 3.5 framework.
Create a static utility class and add something like this:
public static void DoSomething(this ClassA obj, int param1, string param2)
{
//do something
}
Add a reference to the utility class on the page, and this method will appear as a member of ClassA. You can overload existing methods or create new ones this way.