I am new to C#, and I have a problem for which in C++ I would normally use the friend identifier. Now I know the friend keyword doesn't exist in C#, but I don't have any experience with how to work around this (except for making all class variables public properties, which I want to avoid if I can).
I have the following scenario:
public class A
{
public string Info { get; set; }
/* much more data */
}
public class B
{
private A m_instanceOfA;
public B(A a) { m_instanceOfA = a; }
public Info { get return A.info; set A.Info = value; }
/* And some more data of its own*/
}
public class C
{
private A m_instanceOfA;
// I need a constructor of C, which needs to set C.m_instanceOfA
// to the same value as b.m_instanceOfA.
public C(B b) { m_instanceOfA = b.m_instanceOfA ; } // <--- Not allowed!
/* And some more data of its own*/
}
Is there any other clever way, without making B.m_instanceOfA public, to give C access to this variable (only in the constructor)?
You can use the trick shown below to create a method FriendRecieveMessageFromAlice on Bob that can only be called by Alice. An evil class, Eve, won't be able to call that method without using reflection on private members.
I'm curious to know if this or another solution have been suggested before by other people. I've been looking for a solution to that problem for months, and I never saw one that ensured real friend semantics provided that reflection isn't used (you can circumvent nearly anything with it).
Alice and Bob
public interface IKey { }
public class Alice
{
// Alice, Bob and Carol must only have private constructors, so only nested classes can subclass them.
private Alice() { }
public static Alice Create() { return new Alice(); }
private class AlicePrivateKey : Alice, IKey { }
public void PublicSendMessageToBob() {
Bob.Create().FriendRecieveMessageFromAlice<AlicePrivateKey>(42);
}
public void FriendRecieveMessageFromBob<TKey>(int message) where TKey : Bob, IKey {
System.Console.WriteLine("Alice: I recieved message {0} from my friend Bob.", message);
}
}
public class Bob
{
private Bob() { }
public static Bob Create() { return new Bob(); }
private class BobPrivateKey : Bob, IKey { }
public void PublicSendMessageToAlice() {
Alice.Create().FriendRecieveMessageFromBob<BobPrivateKey>(1337);
}
public void FriendRecieveMessageFromAlice<TKey>(int message) where TKey : Alice, IKey {
System.Console.WriteLine("Bob: I recieved message {0} from my friend Alice.", message);
}
}
class Program
{
static void Main(string[] args) {
Alice.Create().PublicSendMessageToBob();
Bob.Create().PublicSendMessageToAlice();
}
}
Eve
public class Eve
{
// Eve can't write that, it won't compile:
// 'Alice.Alice()' is inaccessible due to its protection level
private class EvePrivateKey : Alice, IKey { }
public void PublicSendMesssageToBob() {
// Eve can't write that either:
// 'Alice.AlicePrivateKey' is inaccessible due to its protection level
Bob.Create().FriendRecieveMessageFromAlice<Alice.AlicePrivateKey>(42);
}
}
How it works
The trick is that the method Bob.FriendRecieveMessageFromAlice requires a (dummy) generic type parameter which serves as a token. That generic type must inherit from both Alice, and from a dummy interface IKey.
Since Alice does not implement IKey itself, the caller needs to provide some subclass of Alice which does implement IKey. However, Alice only has private constructors, so it can only be subclassed by nested classes, and not by classes declared elsewhere.
This means that only a class nested in Alice can subclass it to implement IKey. That's what AlicePrivateKey does, and since it is declared private, only Alice can pass it as the generic argument to the Bob.FriendRecieveMessageFromAlice, so only Alice can call that method.
We then do the same thing the other way round so that only Bob can call Alice.FriendRecieveMessageFromBob.
Leaking the key
It is worth noting that, when called, Bob.FriendRecieveMessageFromAlice has access to the TKey generic type parameter, and could use it to spoof a call from Alice on another method OtherClass.OtherMethod<OtherTkey> accepting a OtherTKey : Alice, IKey. It would therefore be safer to make the keys inherit from distinct interfaces: Alice, IBobKey for the first, and Alice, IOtherKey for the second.
Better than C++ friend
Even Bob itself can't call its own method Bob.FriendRecieveMessageFromAlice.
Bob can have multiple friends with distinct friend methods:
// Can only be called by Alice, not by Carol or Bob itself
Bob.FriendRecieveMessageFromAlice <TKey>(int message) where TKey : Alice, IKey { }
// Can only be called by Carol, not by Alice or Bob itself
Bob.FriendRecieveMessageFromCarol <TKey>(int message) where TKey : Carol, IKey { }
I'd be interested to know if there is some way to find tricks like this in a more efficient way than brute-force trial and error. Some kind of "algebra of C#'s type system", that tells us what restrictions can be enforced and what can't, but I haven't seen any discussion on that kind of topic.
Internal
You can use the internal keyword. Your type (or type member) will then only be visible to other types within the same assembly; And also:
If you need your internal types to be visible from other assemblies, you can use the InternalsVisibleToAttribute. This attribute targets your whole assembly and is usually written in the AssemblyInfo.cs file.
PS: Friend keyword doesn't exists in C# but the concept of friendship exists (not exactly the same as the one in C++), it is described on the Friend Assemblies article from the MSDN. Note also that a friend keyword exists in VB.NET and has the exact same behaviour than the C# internal keyword.
You can only use 5 accessibility modifiers:
public Access is not restricted.
protected Access is limited to the containing class or types derived from the containing class.
internal Access is limited to the current assembly.
protected internal
Access is limited to the current assembly or types derived from the containing class.
private
Access is limited to the containing type.
I modified the code you posted, so it should work as you want exactly:
using System.Reflection;
using System.Diagnostics;
public class A
{
public string Info { get; set; }
/* much more data */
}
public class B
{
private A m_instanceOfA;
public string Info { get; set; }
public B(A a) => Info = a;
private readonly ConstructorInfo friend = typeof(C).GetConstructor(new Type[] { typeof(B) });
public A InstanceOfA
{
get
{
if (new StackFrame(1).GetMethod() != friend)
throw new Exception("Call this property only inside the constructor of C");
return this.m_instanceOfA;
}
}
}
public class C
{
private A m_instanceOfA;
// Only the constructor of C can set his m_instanceOfA
// to the same value as b.m_instanceOfA.
public C(B b)
{
Info = b.InstanceOfA; // Call the public property, not the private field. Now it is allowed and it will work too, because you call it inside the constructor of C. In Main method, for example, an exception will be thrown, if you try to get InstanceOfA there.
}
}
I think you're looking for the "internal" keyword - basically only visible to classes in the same assembly
Alternatively you could so something like (excuse the method names!) :
public interface IAmAFriendOfB {
void DoSomethingWithA(A instanceOfA);
}
public class B {
private A m_instanceOfA;
public B(A a) { m_instanceOfA = a; }
public void BeFriendlyWith(IAmAFriendOfB friend) {
friend.DoSomethingWithA(m_instanceOfA);
}
// the rest of your class
}
public class C : IAmAFriendOfB {
private A m_instanceOfA;
public C(B b) {
b.BeFriendlyWith(this);
}
void DoSomethingWithA(A instanceOfA) {
m_instanceOfA = b.m_instanceOfA;
}
}
Here's another alternative using an internal class with a private singleton instance, which allows you to fine-tune which methods are exposed to the pseudo-friend class.
using System;
namespace Test
{
public class A
{
public string Info { get; set; }
/* much more data */
}
public class B
{
private A m_instanceOfA;
public B(A a) { m_instanceOfA = a; }
public string Info
{
get { return m_instanceOfA.Info; }
set { m_instanceOfA.Info = value; }
}
// requires an instance of a private object, this establishes our pseudo-friendship
internal A GetInstanceOfA(C.AGetter getter) { return getter.Get(m_instanceOfA); }
/* And some more data of its own*/
}
public class C
{
private A m_instanceOfA;
private static AGetter m_AGetter; // initialized before first use; not visible outside of C
// class needs to be visible to B, actual instance does not (we call b.GetInstanceOfA from C)
internal class AGetter
{
static AGetter() { m_AGetter = new AGetter(); } // initialize singleton
private AGetter() { } // disallow instantiation except our private singleton in C
public A Get(A a) { return a; } // force a NullReferenceException if calling b.GetInstanceOfA(null)
}
static C()
{
// ensure that m_AGetter is initialized
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(AGetter).TypeHandle);
}
public C(B b)
{
m_instanceOfA = b.GetInstanceOfA(m_AGetter);
}
public string Info
{
get { return m_instanceOfA.Info; }
set { m_instanceOfA.Info = value; }
}
/* And some more data of its own*/
}
public class Test
{
public static void Main()
{
A a = new A();
B b = new B(a);
C c = new C(b);
c.Info = "Hello World!";
Console.WriteLine(a.Info);
}
}
}
Live Demo
The C.AGetter class cannot be instantiated outside of itself, so C.m_AGetter (which is both private and static) represents a singleton instance that is only accessible from within C. As B.GetInstanceOfA requires an instance of C.AGetter, this makes the function useless outside of C. The function is marked internal to minimize its exposure, but the argument should also act as a form of self-documentation that it isn't meant for common use.
The interface alternative risks exposing methods beyond their intended scope (e.g., a class implementing the interface where it should not have access to the exposed methods), while this approach prevents that. Naysayers of friend access may still object to it, but this keeps things much closer to the intended scope.
Related
A is base class
B is derived from A and also C is derived from A
I want only B can access the method of A , C an not access of that same method of A.
class A {
protected void Foo() {
}
}
class B : A {
void Bar() {
this.Foo(); // OK
}
}
class C : A {
void Baz() {
this.Foo(); // I don't want to permit this
}
}
HOW IT POSSIBLE IN c#
I think this look like a problem for Interface segregation principle:
Clients should not be forced to depend upon interfaces that they don't
use.
But in your case this can be rephrased for the class inheritance.
Create pure base class (without a method you want to hide from class C)
public class Base
{
protected void SomeDummyMethod()
{
}
}
Then create your A class which inherit from Base and add a method you what to share for class B
public class A : Base
{
protected void YourFooMethod()
{
}
}
Create B class which inherit from A and will have access to all functionality including YourFooMethod
public class B : A
{
public void Bar()
{
this.YourFooMethod();
}
}
And finally your C class which have all base functionality except YourFooMethod method
public class C : Base
{
public void Bar()
{
this.YourFooMethod(); //Compile error: YourFooMethod is not a member of...
}
}
I suppose you could write code in class A that checks the calling class name against a white list or a black list and throws an exception in the cases you want to disallow, but I would not recommend doing this. That would be very difficult to maintain, and class A should not need to know about every class that extends it.
What you are trying to do is really honestly a bad idea.
C# (and .NET in general) has the access modifiers:
public - Anyone can access
private - Only the containing scope/type can access
protected - Only the containing type and its derived types can access
internal - Only types defined in the same Assembly (or InternalsVisibleTo Assemblies) can access
protected internal - The set-union of protected and internal can access.
You're asking for something in-between private and protected, where you can manually restrict access to named types.
This is not currently possible to enforce, at least at compile-time, in .NET - though if types A and B exist in the same assembly and C exists in a different assembly then internal would work.
At runtime you could enforce this with code-access-security, or more simply: using reflection to get the calling-class's name (this.GetType()), or use a password:
or more simpler: a password requirement:
class A {
private Boolean isAllowedAccess;
protected A(String password) {
this.isAllowedAccess = password == "12345abc";
}
protected void Foo() {
if( !this.isAllowedAccess ) throw new InvalidOperationException();
}
}
class B : A {
public B() : base("12345abc") {
}
void Bar() {
this.Foo(); // OK
}
}
class C : A {
public C() : base(null) {
}
void Baz() {
this.Foo(); // I don't want to permit this
}
}
I have a program that needs to be able to interface with multiple platforms ie read/write files, read/write database or read/write web requests. The platform interface is selected from configuration and does not change while the application is running. I have a single read/write interface class which is inherited by the platform specific classes so that this is abstracted from the rest of the program.
My problem is that I have 10 classes in my framework that will need to use this interface. Instead of making multiple instances of this class, or passing a single reference to every class, I figured it would make sense to make the interface static. Unfortunately I have just learned that Interfaces cannot have static methods, static methods cannot call non-static methods and static methods cannot be abstract.
Can anyone show me another method of approaching this situation?
Edit:
Thanks for everyone's input, here is my solution based on the example given by Patrick Hofman (thank you!)
interface TheInterface
{
void read();
void write();
}
public class X : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class Y : TheInterface
{
public void read() { //do something }
public void write() { //do something }
}
public class FileAccessor
{
public static TheInterface accessor;
public static TheInterface Accessor
{
get
{
if(accessor) return accessor;
}
}
}
This can be called by any class as:
static void Main(string[] args)
{
switch (Config.interface)
{
case "X":
FileAccessor.accessor = new Lazy<X>();
case "Y":
FileAccessor.accessor = new Lazy<Y>();
default:
throw new Lazy<Exception>("Unknown interface: " + Config.interface);
}
FileAccessor.Accessor.read();
}
Indeed, interfaces, or abstract classes can't be static themselves, but the further implementation can. Also, you can use the singleton pattern to make your life easier, and allow inheritance, etc.
public class X : ISomeInterface
{
private X() { }
public static X instance;
public static X Instance
{
get
{
return instance ?? (instance = new X());
}
}
}
Or, using Lazy<T>:
public class X : ISomeInterface
{
private X() { }
public static Lazy<X> instanceLazy = new Lazy<X>(() => new X());
public static X Instance
{
get
{
return instance.Value;
}
}
}
Disclaimer: I am the author of the library described below.
I don't know if this helps you, but I have written a library (very early version yet) that allows you to define static interfaces, by defining normal interfaces and decorating their methods with an attribute named [Static], for example:
public interface IYourInterface
{
[Static]
void DoTheThing();
}
(Note that you don't explicitly add this interface to your implementations.)
Once you have defined the interface, you can instantiate it from within your code with any valid implementation you choose:
return typeof(YourImplementation).ToStaticContract<IYourInterface>();
If the methods can't be found in YourImplementation, this call fails at runtime with an exception.
If the methods are found and this call is successful, then the client code can polymorphically call your static methods like this:
IYourInterface proxy = GetAnImplementation();
proxy.DoTheThing();
You can make a Static Class which has Variable of your Interface.
public static class StaticClass
{
public static ISomeInterface Interface;
}
Now you can access the Instance from everywhere in your Framwork
static void Main(string[] args)
{
StaticClass.Interface = new SomeClass();
}
I know there is a 'internal' keyword and [InternalsVisibleTo] attribute. But how to allow a class in class level that is not in the same assembly to modify private data in ? That is, only allow a particular class in an assembly to access private data but not evey classes under that assembly?
I asked this question before here How to implement C++ like friend relationship in C# but it is not specific enough, so I ask again here.
Other discussion related to the theory and reason why C# not use friend was discussed here
Why does C# not provide the C++ style 'friend' keyword?
I have thought about it and I think I have a solution by reflection. Not sure is it a good way to do it.
If I have SomeClass that has a friend FriendClass. NotFriendClass and FriendClass are in the same assembly but only FriendClass can access SomeClass's private data. Here is what SomeClass needs:
class SomeClass
{
private bool isMyFriend()
{
StackTrace st = new StackTrace();
StackFrame callerSF = st.GetFrame(2);
MethodBase mb = callerSF.GetMethod();
Type callerType = mb.DeclaringType;
// FriendClass is my friend
if (typeof(FriendClass) == callerType)
return true;
else
return false;
}
// ....
In this method SomeClass checks whether the caller class is his friend. Yes it has a hardcoded if (typeof(FriendClass) == callerType) but C++ friend also need to hardcode the class name in the declaration.
For those "friend-awared" methods of SomeClass, it should be like:
public bool SetData(int x)
{
if (!isMyFriend())
return false;
this.privateData = x;
return true;
}
The only problem is it is a run-time checking. But still, I think it is good enough for porting some program from C++ to C# using friend.
I usually translate cases where a friend keyword seems handy into a pattern where a class itself determines which classes can instantiate it, without breaking proper OO-design.
The idea is that the class that wants control over who can instantiate, offers friendship to the classes that are allowed to get an instance of it. For example, class InControl allows classes ChosenOne and ChosenTwo to obtain instances of InControl.
A 'chosen' class (i.e. ChosenOne or ChosenTwo) can 'engage' the friendship offered by InControl with an instance of itself (friendship.engage(this)) and the friendship in turn can 'accept' that instance by providing it an instance of InControl (friend.accept(new InControl())).
The actual friendship is implemented with a nested single instance Friendship class. Friendship is confined to 'chosen' classes using a generic IFriendship interface with T being a chosen class. In turn, each 'chosen' class needs to implement the generic IFriendable interface with T being InControl, to be able to receive an instance of InControl.
The InControl class has a private constructor to avoid instantiation by anyone else but friends:
public interface IFriendable<T>
{
void accept(T friend);
}
public interface IFriendship<T>
{
void engage(T friend);
}
public class ChosenOne : IFriendable<InControl>
{
private InControl _friend { get; set; }
private ChosenOne()
{
InControl.friendship.engage(this);
}
public void accept(InControl friend)
{
_friend = friend;
}
}
public class ChosenTwo : IFriendable<InControl>
{
private InControl _friend { get; set; }
private ChosenTwo()
{
InControl.friendship.engage(this);
}
public void accept(InControl friend)
{
_friend = friend;
}
}
public class InControl
{
public interface IFriendship : IFriendship<ChosenOne>, IFriendship<ChosenTwo> { }
public static IFriendship friendship { get { return Friendship.instance; } }
private class Friendship : IFriendship
{
static Friendship()
{
}
internal static readonly Friendship instance = new Friendship();
public void engage(ChosenOne friend)
{
friend.accept(new InControl());
}
public void engage(ChosenTwo friend)
{
friend.accept(new InControl());
}
}
private InControl()
{
}
}
The base class user should access the original method
class A
public init()
The derived class user should aceess ONLY the derived method.
class B
public init(int info)
I cannot use "override" bc there's a different signature.
What options do I have so that the derived class user does not see two methods.
Notes.
All in all I just need two classes that share some code. Inheritance is not a must.
But simplicity for the user of B is a priority.
This is a big code smell (and violates some basic OOP tenets) and, to the best of my knowledge, can not be done in any language. In OOP, an instance of B is an instance of A; this is polymorphism. So if A has a public method named init accepting no parameters, then so does B.
What are you trying to do this for?
Edit: Now that you've added the edit that states that inheritance is not a must, just use composition to share code. Give B a private instance of A, for example.
According to the Liskov principle you simply cannot do that, because it would violate this principle. The best thing you can to is override init() in the derived class and make it throw an exception every time it's invoked, stating that the user should use init(int info) and rely on the test to catch the errors.
Why you can't simple replace the init() method or even make it protected?
The Liskov principle states (rephrased) that where an instance of class A is required, an isntance of class B extends A can be passed.
If a method expects A and wants to call init() on it and you pass B (which extends A) to it with a protected init() the method will fail. This is the reason why the code will not even compile.
What you're asking for is impossible, due to the nature of the type system. Any instance of B can be thought of as an A, so you can call any of A's methods (including Init()). The best you can do is overload Init() in B and throw an exception to catch this at runtime.
public class B
{
void Init()
{
throw new NotSupportedException();
}
}
Contrary to some answers/comments here, what you are asking for would have a real use if it existed:
class Derived : Base
{
This can be seen by considering the workaround:
class Derived
{
private Base _base = new Base();
In other words, it's not really a base class at all, but a hidden part of the implementation.
The downside with this workaround is: what Base has an abstract method that you have to supply? You have to write this:
class Derived
{
class ActualDerived : Base
{
// override abstract method(s)
}
private Base _base = new ActualDerived();
This is the whole point of private inheritance (as found in C++) - it's for situations when you want to inherit the implementation but not the "interface" (in the informal sense).
But in C#, it's not available.
Presumabely A and B have something in common. Can you factor that out into a different base class?
public class Base
{
... common stuff ...
}
public class A : Base
{
public void Init()
{
}
}
public class B : Base
{
public void Init(int info)
{
}
}
if you need polymorphism then references to Base or, better yet, Thomas' interface are the way to go.
Instead of inheritance, use an interface as a "middle man":
public interface IAllThatYouNeed
{
public void DoSomeStuff();
}
public class A : IAllThatYouNeed
{
public void Init() {
// do stuff
}
}
public class B : IAllThatYouNeed
{
public void Init(int info) {
// do stuff
}
}
it looks like it's not yet possible
i tried to do something like this:
public class B : A
{
private override void Init() { }
public void Init(int x)
{ }
}
but Init() it's still visible from the A class
There is no perfect solution here. Some possible ways to do it:
An approach would be to make A.Init() virtual, override it in B and make it throw a NotImplementedException/InvalidOperationException.
Init() stays visible, but the user finds out very quickly that it is not to be used (make it explicit that Init(int info) is to be used in the XML documentation and in the message of the exception).
If you don't care about the inheritance part and just want to use the functionalities of class A in class B, don't have B deriving from A and make B instantiate A and use its functionalities.
Edit:
You can use an interface implementing the common operations in order to retain inheritance while avoiding to implement Init() in B:
public interface IOperations
{
void DoStuff();
void Foo();
}
public class A : IOperations
{
public void Init()
{
// Do class A init stuff
}
#region IOperations Members
public void DoStuff()
{
// ...
}
public void Foo()
{
// ...
}
#endregion
}
public class B : IOperations
{
A _operations = new A();
public void Init(int initData)
{
_operations.Init();
// Do class B init stuff
}
#region IOperations Members
public void DoStuff()
{
_operations.DoStuff();
}
public void Foo()
{
_operations.Foo();
}
#endregion
}
This can be made even better by using a factory:
public static class OperationsFactory
{
public static IOperations CreateOperations()
{
A result = new A();
result.Init();
return result;
}
public static IOperations CreateOperations(int initData)
{
B result = new B();
result.Init(initData);
return result;
}
}
This way instantiation code is well encapsulated, the difference between the two Init() methods is hidden from the user code.
Coming from a C++ background, I've run into a snag with overloading based on a specific instance of a generic type. The following doesn't work since only once instance of the code for the Foo<T> class is ever generated, so inside the Method, the type of this is simply Foo<T>, not Foo<A> or Foo<B> as I'd hoped. In C++ I'm used to templates being instantiated as unique types.
using System.Collections.Generic;
class A
{
// Concrete class
}
class B
{
// Concrete class
}
class Bar
{
public void OverloadedMethod(Foo<A> a) {} // do some A related stuff
public void OverloadedMethod(Foo<B> b) {} // do some B related stuff
public void OverloadedMethod(OtherFoo of) {} // do some other stuff
public void VisitFoo(FooBase fb) { fb.Method(this); }
}
abstract class FooBase
{
public abstract void Method(Bar b);
}
class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
class OtherFoo : FooBase
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Program
{
static void Main(string[] args)
{
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo<A>());
ListOfFoos.Add(new Foo<B>());
Bar b = new Bar();
foreach (FooBase fb in ListOfFoos)
b.VisitFoo(fb);
// Hopefully call each of the Bar::Overloaded methods
}
}
Is there a way to get something like this to work in C#? I'd rather not have to duplicate the code in Foo as separate classes for every type I want to use it for.
Edit:
Hopefully this is a little clearer.
I now have a genuinely complete piece of code which demonstrates the problem. Note to OP: please try compiling your code before posting it. There were a bunch of things I had to do to get this far. It's good to make it as easy as possible for other people to help you. I've also removed a bunch of extraneous bits. OtherFoo isn't really relevant here, nor is FooBase.
class A {}
class B {}
class Bar
{
public static void OverloadedMethod(Foo<A> a) { }
public static void OverloadedMethod(Foo<B> b) { }
}
class Foo<T>
{
// Class that deals with As and Bs in an identical fashion.
public void Method()
{
// Doesn't compile here
Bar.OverloadedMethod(this);
}
}
Yes, this doesn't compile. What did you expect it to do, exactly? Bear in mind that the overload resolution is performed at compile time, not execution time. As fallen888 says, you could cast and call the appropriate overloaded method - but which of the two overloads would you expect the compiler to pick otherwise? What do you want it to do with Foo<string> instead of Foo<A> or Foo<B>?
This all goes to demonstrate that .NET generics are indeed significantly different from C++ templates, of course...
I haven't tried it but it seems you should be able to achieve what you want by making A & B visitable (e.g. with the acyclic visitor pattern).
This works for the static case. Dealing with instance functions would be a bit more complicated. This post from Jon Skeet might provide a reasonable way to deal with instance methods.
class Program
{
static void Main(string[] args)
{
var testA = new Foo<A>();
testA.Method();
var testB = new Foo<B>();
testB.Method();
Console.ReadLine();
var testString = new Foo<string>(); //Fails
testString.Method();
Console.ReadLine();
}
}
class A { }
class B { }
class Bar
{
public static void OverloadedMethod(Foo<A> a)
{
Console.WriteLine("A");
}
public static void OverloadedMethod(Foo<B> b)
{
Console.WriteLine("B");
}
}
class Foo<T>
{
static Foo()
{
overloaded = (Action<Foo<T>>)Delegate.CreateDelegate(typeof(Action<Foo<T>>), typeof(Bar).GetMethod("OverloadedMethod", new Type[] { typeof(Foo<T>) }));
}
public void Method()
{
overloaded(this);
}
private static readonly Action<Foo<T>> overloaded;
}
Edit: I'm not sure that you can complete this as you're attempting. I've tried all sorts of tricks to attempt to get this to work and can't get it to compile. The best I can do is to pull the method call outside of my Generic class. If your method call is outside, then you can specifically define what T is in the generic. However, inside the method, at compile time, the compiler doesn't know what T will be so it doesn't know which overloaded method to call. The only way I can see around this is to use a switch to determine the type of T and manually specify the overload to call.
The best I can do is this, which isn't quite what you're after, but it could be used to a similar effect:
class Stuff<T>
{
public T value { get; set; }
}
class Program
{
static void DummyFunc(Stuff<int> inst)
{
Console.WriteLine("Stuff<int>: {0}", inst.value.ToString());
}
static void DummyFunc(Stuff<string> inst)
{
Console.WriteLine("Stuff<string>: {0}", inst.value);
}
static void DummyFunc(int value)
{
Console.WriteLine("int: {0}", value.ToString());
}
static void DummyFunc(string value)
{
Console.WriteLine("string: {0}", value);
}
static void Main(string[] args)
{
var a = new Stuff<string>();
a.value = "HelloWorld";
var b = new Stuff<int>();
b.value = 1;
var c = "HelloWorld";
var d = 1;
DummyFunc(a);
DummyFunc(b);
DummyFunc(c);
DummyFunc(d);
}
}
and got output:
Stuff<string>: HelloWorld
Stuff<int>: 1
string: HelloWorld
int: 1
I've got four overloaded functions referencing two referencing generic classes (one for int and one for string) and two referencing regular types (one for int and one for string) and it all works okay... is this what you're after?
Edit: The problem doesn't seem to be with the calling of the overloaded methods, it has to do with your foreach which is trying to convert all items in the list to the same type as the first in order to reference the overloaded method. The first item that doesn't conform to that exact definition will cause your compile to fail.
I was hoping to find an easier way to do this but for now I'm going with this:
Replace Foo<T> class with these classes:
abstract class Foo<T> : FooBase
{
// Class that deals with As and Bs in an identical fashion.
}
class Foo_A : Foo<A>
{
public override void Method(Bar b)
{
b.OverloadedMethod(this);
}
}
class Foo_B : Foo<B>
{
public override void Method(Bar b)
{
// Doesn't compile here
b.OverloadedMethod(this);
}
}
And change the instantiations to
List<FooBase> ListOfFoos = new List<FooBase>();
ListOfFoos.Add(new OtherFoo());
ListOfFoos.Add(new Foo_A());
ListOfFoos.Add(new Foo_B());
This at least doesn't require dublicating the code in Foo<T>, and just requires me to forward the constructors.