abstract class Foo
{
private readonly FooAttributeCollection attributes;
public Foo(FooAttributeCollection attributes)
{
this.attributes = attributes;
}
}
class FooAttributeCollection
{
public FooAttributeCollection(Foo owner)
{
}
}
class Bar : Foo
{
public Bar() : base(new FooAttributeCollection(this))
{
}
}
Supposing that I have to write a code like above. and the classes Foo and FooAttributeCollection cannot be modified.
When I write Bar class like that, an error mentioned below:
'this' keyword cannot be used in this context.
occurs near the line base(...)
Is there any good idea to handle with this matter?
If Foo and FooAttributeCollection can't be modified, this code seems to be a bad design.
To instantiate a derivated Foo class you must instantiate FooAttributeCollection before and to instantiate FooAttributeCollection you must instantiate the same derivated Foo class.
Its a endless circular dependency impossible to resolve without 'cheating'
perhaps this problem can be resolve by refection (as say by Uwe Keim), or by using real proxy/dynamic proxy to create a proxy of DerivedClass.
Why don't affect attributes in abstract class ? If you want in FooAttributeCollection you can cast owner in Bar class.
abstract class Foo
{
private readonly FooAttributeCollection attributes;
public Foo(FooAttributeCollection attributes=null)
{
if(attributes = null) {attributes = new FooAttributeCollection(this);}
this.attributes = attributes;
}
}
class FooAttributeCollection
{
public FooAttributeCollection(Foo owner)
{
var ownerInBar = owner as Bar;
}
}
class Bar : Foo
{
public Bar() : base()
{
}
}
You can't write:
public Bar() : base(new FooAttributeCollection(this))
Because this, the current object, must be put in the implementation of a method, not in the method signature: here you have no access to the current instance of the object.
You can't do a such thing in every method declaration because you are out of the implementation scope, you are in the type def scope i.e. in the "interface" of the class, in its definition.
The use of calling base or side constructor with base or this keyword is a particular language construction to pass parameters that are not the instance of the class itself.
You can use the #Tohm solution to solve your goal.
the class needs to be constructed before you can access the this keyword.
You can try the bellow.
class Bar : Foo
{
private readonly FooAttributeCollection attributes;
public Bar() : base(null)
{
var attributes = new FooAttributeCollection(this);
}
}
Try this way:
public class Bar : Foo
{
public Bar(FooAttributeCollection attributes) : base(attributes)
{
}
}
Other Example:
public class BaseClass
{
int num;
public BaseClass(int i)
{
num = i;
Console.WriteLine("in BaseClass(int i)");
}
}
public class DerivedClass : BaseClass
{
// This constructor will call BaseClass.BaseClass(int i)
public DerivedClass(int i) : base(i)
{
}
}
Related
I have a class A, and a class AStore. My requirement is to prevent all other methods from initializing an instance of class A, which they should get an instance from AStore. In addition, I also need to access the member functions of A from the instance.
Factory pattern is not suitable for this problem as the constructor of A is still public. Ideally, it should throw compilation error when calling the constructor of class A while having access to its member functions.
Can I get C# solutions to this?
For restricting others to create an instance of class A you can use a private constructor and a static factory method to get the instance of that class.
public class A
{
private A(){}
public static A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
To enforce instance creation of A only via Astore you can use protected modifier and derive AStore from A. That way, only AStore will have access to its protected members like 'constructor' or 'factory method':
public class Astore : A
{
public A GetInstanceOfA()
{
return base.GetInstance();
}
}
public class A
{
protected A() { }
protected A GetInstance()
{
return new A();
}
public void MemberFunctionOfA()
{
// blah blah...
}
}
//Usage
public class ConsumerClass
{
public void Test()
{
var a = new A(); // Compile error
a = new Astore().GetInstanceOfA();
a.MemberFunctionOfA();
}
}
But there're still chances that another class say 'UnWantedStore' can derive from A and serve instance of A.
Another approach is moving AStore and A classes to the dedicated project and make constructor of A class internal.
// Project A
namespace ProjectA
{
public class A
{
public int PropertyOne { get; set; }
public string PropertyTwo { get; set; }
internal A() {}
}
public class AStore
{
public A CreateA()
{
//internal constructor can be used
return A();
}
}
}
// Project ConsumerOfA
namespace ConsumerOfA
{
public static void UseA()
{
var store = new AStore();
var instanceOfA = store.CreateA();
// have access to the A's public members
}
}
With this approach you will get perfect encapsulation you trying to achive.
Abstract classes to the rescue!
Indeed, there's yet another possible approach! I've never used it but it might work in your scenario. See the following code sample:
public abstract class A
{
public string Text { get; set; }
public string SayHello() => "hello world!";
}
public class AStore
{
private class AInternal : A {}
public void DoStuff()
{
A a = new AInternal();
a.Text = "whatever";
string helloText = a.SayHello();
}
}
Let's explain the approach:
Class A is abstract, therefore it can't be instantiated.
Class AStore implements a private nested class called AInternal which just inherits A to let AStore members be able to instantiate A. Since AInternal is private, no other class than AStore can instantiate AInternal!
Class AStore can access public A members because AInternal inherits A!
You can do this with reflection too:
public class ClassA
{
// The constructor(s) have to be private
private ClassA() { }
// Whatever other code you want
}
public class ClassB
{
public static ClassA GetClassAInstance()
{
// Use reflection to get the private default constructor
ConstructorInfo constructor = typeof(ClassA).GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { }, null);
ClassA instance = constructor.Invoke(new object[] { }) as ClassA;
return instance;
}
}
You can find more information on the GetConstructor method here.
Is there a neat way to specify that a class must contain a factory method that returns the same kind of object as the class that overrides the abstract method? (Edit: Or as Johnathon Sullinger more eloquently puts it, [...] have a base class enforce a child class to implement a method that returns an instance of the child class itself, and not allow returning an instance of any other Type that inherits from the base class.)
For example, if I've got two classes, SimpleFoo : BaseFoo and FancyFoo : BaseFoo, can I define an abstract factory method public TFoo WithSomeProp(SomeProp prop) where TFoo is a type parameter that is somehow fixed by the abstract method definition to the particular class that overrides it?
I had hopes of compile-time guarantees that either
a concrete WithSomeProp method definition in SomeFoo : BaseFoo will only be able to produce SomeFoos. If static abstract method definitions were legal, perhaps the following (pseudo-syntax) method extension best expresses this need:
public static abstract TFoo WithSomeProp<TFoo>(this TFoo source, SomeProp prop)
where TFoo : BaseFoo;
I don't think this is possible in C#.
or at least some way to parameterize the return type in an abstract method, e.g.
public abstract TFoo WithSomeProp<TFoo>(SomeProp prop)
where TFoo : BaseFoo;
This wouldn't prevent FancyFoo.WithSomeProp from returning SimpleFoos, but ok.
This abstract method itself seems to work, but my concrete definition then fails:
public override SimpleFoo WithSomeProp(SomeProp prop)
{
return new SimpleFoo(this.SomeOtherProp, ..., prop);
}
with the warning
no suitable method found to override
It appears to me that specifying type parameters in an abstract method does not allow fixing them in the overrides of those definitions, but rather it specifies that "A method with a type parameter should exist".
For now I simply have public abstract BaseFoo WithSomeProp(SomeProp prop);.
It sounds like what you want to do, is have a base class enforce a child class to implement a method that returns an instance of the child class itself, and not allow returning an instance of any other Type that inherits from the base class. Unfortunately, to the best of my knowledge, that is not something you can do.
You can however force the child-class to specify what it's Type is to the base class, so that the base class can then enforce that the return value must be the Type specified by the child-class.
For instance, given a base class called BaseFactory, and BaseFactory<T>, we can create an abstract class that requires children to specify to the parent, what type the creation method returns. We include a BaseFactory class so we can constrain T to only being children classes of BaseFactory.
EDIT
I'll leave the original answer below in the event that it helps, but after some thought, I think I've got a better solution for you.
You'll still need the base class to take a generic argument that defines what the child Type is. The difference now however is that the base class has a static creation method instead of instance methods. You can use this creation method to create a new instance of the child class, and optionally invoke a callback for configuring the property values on the new instance before you return it.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory, new()
{
public static TImpl Create(Action<TImpl> itemConfiguration = null)
{
var child = new TImpl();
itemConfiguration?.Invoke(child);
return child;
}
}
You then just create your children classes normally, without worrying about overriding any methods.
public class Foo : BaseFactory<Foo>
{
public bool IsCompleted { get; set; }
public int Percentage { get; set; }
public string Data { get; set; }
}
public class Bar : BaseFactory<Bar>
{
public string Username { get; set; }
}
Then you would use the factory as-such.
class Program
{
static void Main(string[] args)
{
// Both work
Bar bar1 = Bar.Create();
Foo foo1 = Foo.Create();
// Won't compile because of different Types.
Bar bar2 = Foo.Create();
// Allows for configuring the properties
Bar bar3 = Bar.Create(instanceBar => instanceBar.Username = "Jane Done");
Foo foo2 = Foo.Create(instanceFoo =>
{
instanceFoo.IsCompleted = true;
instanceFoo.Percentage = 100;
instanceFoo.Data = "My work here is done.";
});
}
Original Answer
The BaseFactory<T> will be reponsible for creating a new instance of TImpl and giving it back.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory
{
public abstract TImpl WithSomeProp();
}
Now, your child class can be created, and inherit from BaseFactory<T>, telling the base class that T represents itself. This means the child can only ever return itself.
public class Foo : BaseFactory<Foo>
{
public override Foo WithSomeProp()
{
return new Foo();
}
}
public class Bar : BaseFactory<Bar>
{
public override Bar WithSomeProp()
{
return new Bar();
}
}
Then you would use it like:
class Program
{
static void Main(string[] args)
{
var obj1 = new Bar();
// Works
Bar obj2 = obj1.WithSomeProp();
// Won't compile because obj1 returns Bar.
Foo obj3 = obj1.WithSomeProp();
}
}
If you really want to make sure that the generic specified is the same as the owning Type, you could instead make WithSomeProp a protected method, so that children classes can only see it. Then, you create a public method on the base class that can do type checking.
public abstract class BaseFactory { }
public abstract class BaseFactory<TImpl> : BaseFactory where TImpl : BaseFactory
{
protected abstract TImpl WithSomeProp();
public TImpl Create()
{
Type myType = this.GetType();
if (typeof(TImpl) != myType)
{
throw new InvalidOperationException($"{myType.Name} can not create instances of itself because the generic argument it provided to the factory is of a different Type.");
}
return this.WithSomeProp();
}
}
public class Foo : BaseFactory<Foo>
{
protected override Foo WithSomeProp()
{
return new Foo();
}
}
public class Bar : BaseFactory<Bar>
{
protected override Bar WithSomeProp()
{
return new Bar();
}
}
class Program
{
static void Main(string[] args)
{
var obj1 = new Bar();
// Works
Bar obj2 = obj1.Create();
// Won't compile because obj1 returns Bar.
Foo obj3 = obj1.Create();
}
}
Now, if you create a child class that passes a different Type as T, the base class will catch it and throw an exception.
// Throws exception when BaseFactory.Create() is called, even though this compiles fine.
public class Bar : BaseFactory<Foo>
{
protected override Foo WithSomeProp()
{
return new Foo();
}
}
Not sure if this gets you what you wanted at least, but I think this will probably be the closest thing you can get.
Inspired by Johnathon Sullinger's fine answer, here is the code I ended with. (I added a theme.)
I passed the type parameter T along with the class definition and constrained that T : Base<T>.
BaseHyperLink.cs:
public abstract class BaseHyperLink<THyperLink> : Entity<int>
where THyperLink : BaseHyperLink<THyperLink>
{
protected BaseHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType)
: base(id)
{
this.HyperLink = hyperLink;
this.ContentType = contentType;
this.DocumentType = documentType;
}
public Uri HyperLink { get; }
public ContentType ContentType { get; }
public DocumentType DocumentType { get; }
public abstract THyperLink WithContentType(ContentType contentType);
}
SharedHyperLink.cs:
public sealed class SharedHyperLink : BaseHyperLink<SharedHyperLink>
{
public SharedHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType)
: base(id, hyperLink, contentType, documentType)
{
}
public override SharedHyperLink WithContentType(ContentType contentType)
{
return new SharedHyperLink(this.Id, contentType, this.DocumentType);
}
}
MarkedHyperLink.cs:
public sealed class MarkedHyperLink : BaseHyperLink<MarkedHyperLink>
{
public MarkedHyperLink(int? id, Uri hyperLink, ContentType contentType, DocumentType documentType, Mark mark)
: base(id, hyperLink, contentType, documentType)
{
this.Mark = mark;
}
public Mark Mark { get; }
public override MarkedHyperLink WithContentType(ContentType contentType)
{
return new MarkedHyperLink(this.Id, contentType, this.DocumentType, this.Mark);
}
}
I have a class Foo that has a field _customObject that must be initialized. I also have a class Bar that inherits from Foo:
public abstract class Foo
{
protected CustomObject _customObject;
public Foo()
{
// Do stuff
}
// Other methods that use _customObject
}
public class Bar : Foo
{
// Constructor and other methods
}
I can not initialize the object _customObject in Foo because every child inherited contains a different child of CustomObject, so it must be initialized in every child class:
public class Bar : Foo
{
public Bar()
{
_customObject = new CustomObjectInherited1();
}
}
public class Baz : Foo
{
public Baz()
{
_customObject = new CustomObjectInherited2();
}
}
Other people are going to implement new classes that inherit from Foo, so I was wondering if there is a way that an error in build time is shown, similar to when an abstract method is not implemented. If CustomObject is not initialized, a NullReferenceException will be thrown due to the use of the _customObject variable, ending in an application crash.
You can add a parameter to your Foo constructor:
public abstract class Foo
{
protected CustomObject _customObject;
public Foo(CustomObject obj)
{
// Do stuff
_customObject = obj;
}
// Other methods that use _customObject
}
Your derived classes will then be forced to call it, passing in a CustomObject, or something derived from it:
public class Bar : Foo
{
public Bar():base(new CustomObjectInherited1())
{
}
}
Not calling the base constructor will result in a compile time error. This doesn't entirely protect you, as someone could still pass null to the base constructor, but at least they'll have an explanation as to why they're getting a NullReferenceError at runtime.
You can force it by creating a abstract method which requires child classes to override it.
public abstract class Foo
{
protected abstract CustomObject CreateCustomObject();
}
public class Bar : Foo
{
protected override CustomObject CreateCustomObject()
{
return new BarCustomObject();
}
}
Or my favorite solution: Enforce it by generic constraints.
public abstract class Foo<T> : where T : CustomObject, new()
{
protected T _customObject;
public Foo()
{
this.CustomObject = new T();
}
}
public class Bar : Foo<BarCustomObject>
{
}
The answer provided by "James Thorpe" is correct (I've upvoted it already), but I wanted to share just another option here:
You could mark your class as abstract and introduce an abstract property instead of the "_customObject" field. That way, at least the first initializer will be forced to implement it. The downside is that you'll loose the enforcement on subsequent level subclasses:
public abstract class Foo
{
protected abstract CustomObject CustomObject {get; }
public Foo()
{
// Do stuff
}
// Other methods that use _customObject
}
public class Bar : Foo
{
// Constructor and other methods
protected override CustomObject CustomObject
{
get { return "X"; }
}
}
Also, with the first solution it's possible to validate the passed in value in the constructor - though, that'll be a runtime validation.
If I want a constructor that is only accessible from child classes I can use the protected key word in the constructor.
Now I want the opposite.
My child class should have an constructor that can be accessed by its base class but not from any other class.
Is this even possible?
This is my current code. the problem is that the child classes have a public constructor.
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(dataSet);
}
}
public class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(DataSet dataSet)
{
}
}
I think you have two options:
Make the child constructor internal. This means it will be accessible from all types in the same assembly, but that should be enough in most cases.
Make the child classes nested in the base class:
public abstract class BaseClass
{
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(dataTable);
}
private class Child1 : BaseClass
{
public Child1(DataTable dataTable)
{
}
}
}
This way, BaseClass can use the constructor, but no other outside type can do that (or even see the child class).
I think I just solved it by myself. After reading svicks solution with nested classes, I thought why not use an protected nested class as an argument?
Nobody from outside is able to create an instance of Arg and the public contructors from my child classes can only be used by BaseClass which can create Arg<T> instances.
public abstract class BaseClass
{
protected class Arg<T>
{
public T Value { get; set; }
public Arg(T value) { this.Value = value; }
}
public static BaseClass CreateInstance(DataTable dataTable)
{
return new Child1(new Arg<DataTable>(dataTable));
}
public static BaseClass CreateInstance(DataSet dataSet)
{
return new Child2(new Arg<DataSet>(dataSet));
}
}
public class Child1 : BaseClass
{
public Child1(Arg<DataTable> arg) : this(arg.Value) { }
private Child1(DataTable dataTable)
{
}
}
public class Child2 : BaseClass
{
public Child2(Arg<DataSet> arg) : this(arg.Value) { }
public Child2(DataSet dataSet)
{
}
}
Answer to the question is "NO"
There is no such thing exists in the OOP that allow child class constructor to visible only to the Base Class of it...
One could enforce the desired behavior at run-time by having the base constructor accept a ref parameter, and do something like (not threadsafe):
private int myMagicCounter;
public DerivedClass makeDerived(whatever) // A factory method
{
DerivedClass newThing;
try
{
... do whatever preparation
newThing = new DerivedClass(ref myMagicCounter, whatever);
}
finally
{
... do whatever cleanup
}
return newThing;
}
BaseClass(ref int magicCounter, whatever...)
{
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
myMagicCounter++;
if (magicCounter != myMagicCounter)
throw new InvalidOperationException();
}
Note that it will be impossible for a derived class constructor call to get control without having done the factory method's preparation, or to return control to its caller without doing the factory method's cleanup. There will, however, be nothing to prevent the derived-class constructor from passing its partially-constructed instance to outside code which may do whatever it likes with it for an arbitrary amount of time before returning control to the factory method.
Pass and register a factory delegate from the type initializer of derived classes then you just get the job done:
public abstract class BaseClass {
static readonly Dictionary<Type, Delegate>
m_factories = new Dictionary<Type, Delegate> { };
public static BaseClass CreateInstance(DataTable dataTable) {
var type = typeof(Child1);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child1)m_factories[type].DynamicInvoke(dataTable);
}
public static BaseClass CreateInstance(DataSet dataSet) {
var type = typeof(Child2);
RuntimeHelpers.RunClassConstructor(type.TypeHandle);
return (Child2)m_factories[type].DynamicInvoke(dataSet);
}
protected static void AddFactory<TArgs, T>(Func<TArgs, T> factory) {
m_factories.Add(typeof(T), factory);
}
}
public class Child1:BaseClass {
Child1(DataTable dataTable) {
}
static Child1() {
BaseClass.AddFactory((DataTable dt) => new Child1(dt));
}
}
public class Child2:BaseClass {
Child2(DataSet dataSet) {
}
static Child2() {
BaseClass.AddFactory((DataSet ds) => new Child2(ds));
}
}
public static class TestClass {
public static void TestMethod() {
var child2 = BaseClass.CreateInstance(new DataSet { });
var child1 = BaseClass.CreateInstance(new DataTable { });
}
}
If all of the derived classes inherited from the base class directly then don't you worry about the collision of registration -- no body can access a constructor from another class.
For TArgs of Func<TArgs, T> you might want to declare it like variadic generic arguments although it's just not a feature of C♯, Tuple is one of the approaches to simulate it. For more information on this topic, you might want to have a look at:
Simulate variadic templates in c#
I have the following situation:
public interface IStuffer
{
public string Foo { get; }
}
public class BaseClass
{
public static string Foo { get { ... } }
}
public class MyClass : BaseClass, IStuffer
{
}
This won't build because MyClass needs a Foo member. How can I use BaseClass's Foo implementation to satisfy MyClass's requirement for Foo?
It's because Foo is a static member of the BaseClass. Just take away the static keyword!
public class BaseClass
{
public string Foo { get { ... } }
}
Edit: Else if you really want it to stay static, you could use an explicit implementation
public class MyClass : BaseClass, IStuffer
{
string IStuffer.Foo { get { return BaseClass.Foo; } }
}
The problem is that your interface expects a NON-static "string Foo", if you make Foo Non-Static in BaseClass then it will satisfy your Interface :)
Good Luck
Interfaces cannot support static properties or methods. If you have an interface, all methods of that interface must be instance rather than class scope.
In two ways:
1. Rename Foo to something else and add a method Foo like this:
public class BaseClass
{
public static string FormerlyCalledFoo { get { ... } }
public string Foo { get { ... } }
}
2. If you absolutely must have a static Foo property then you can implement the IStuffer interface as an explicit interface implementation like this:
public class BaseClass : IStuffer
{
public static string Foo { get { ... } }
string IStuffer.Foo { get { ... } }
}
If using the latter method, then you have to be aware that you have to cast instances of BaseClass to IStuffer to access the IStuffer.Foo property