In Java I can instantiate an on-the-spot implementation of an interface:
interface Rubbable {
public void rub();
}
...
Rubbable r = new Rubbable() {
#Override
public void rub() {
// implementation
}
};
Like, a one-time implementation kind of thing.
I've tried to do the same thing with an abstract class in C#
public abstract class Foo
{
public abstract Bar Method();
}
Foo f = new Foo
{
public override Bar Method()
{
return new Bar();
}
}
But I'm getting the error
Cannot create an instance of the abstract type or interface 'Foo'
Can I instantiate an abstract class on-the-spot as I would like to? Some kind of, one-time-implementation without having to dedicate a whole class declaration in another part of the codebase to it.
Such a feature is not available in c#. A workaround could be to use delegates:
public class DelegateFoo : Foo {
private Func<Bar> barMethod();
public DelegateFoo(Func<Bar> tmp) => barMethod = tmp;
public override Bar Method() => barMethod();
}
var f = new DelegateFoo(() => new Bar());
But in such a simple case I the class does not add anything, so you might as well use a delegate directly.
Related
Is it possible to overload constructors in C# so that the program chooses to use one constructor if the argument is of a derived class and a different if it is the base class. For instance
class BaseClass {...}
class DerivedClass : BaseClass {...}
class foo
{
public foo(DerivedClass bar)
{
//do one thing
}
public foo(BaseClass bar)
{
//do another
}
}
That is, I want the program to pick the correct constructor based on the object type.
I agree with everyone else that this feels like a code smell, but if you actually compile your code and run it, you'll find that it already works the way you want it to. For instance, this does exactly what you want it to do, for better or for worse.
class Program
{
static void Main(string[] args)
{
var b = new BaseClass();
var d = new DerivedClass();
var f = new foo(d);
//prints Derived Constructor
var e = new foo(b);
//prints Base Constructor
}
}
public class BaseClass {
public BaseClass()
{
}
}
public class DerivedClass : BaseClass
{
public DerivedClass()
{
}
}
class foo
{
public foo(DerivedClass bar)
{
//do one thing
Console.WriteLine("Derived Constructor");
}
public foo(BaseClass bar)
{
Console.WriteLine("Base Constructor");
}
}
I think the best answer for your question is a bit indirect, but the best proximate answer to your question would be along the lines of this:
Edit: correcting incorrect is syntax usage and making it more specific
public foo(BaseClass foobar) {
if (foobar?.GetType() == typeof(BaseClass)) {
//do something
}
else { // do something different }
}
That being said, I don't think that this is necessarily the optimum way to structure your code; making decisions based on object type can be a signal that it's time to leverage polymorphism via abstract/virtual classes and methods. You're better off IMO doing something like this:
public BaseClass {
public virtual void DoSomething() {...}
}
public DerivedClass : BaseClass {
public override void DoSomething() {...}
}
public foo(BaseClass foobar) {
foobar.DoSomething();
}
If you cast your object in your BaseClass the good constructor will be called.
Like so:
void Main()
{
var object2 = new DerivedClass();
var temp = new Allo((BaseClass)object2);
}
public class Allo
{
public Allo(BaseClass value)
{
Console.WriteLine("baseclass");
}
public Allo(DerivedClass value)
{
Console.WriteLine("derivedclass");
}
}
public class BaseClass
{
}
public class DerivedClass : BaseClass
{
}
Output:
baseclass
When I wrote a simple version of the program shown above, it did correctly choose the derived class-method when the constructor was called with the derived class.
[I was getting strange behavior when I tested as part of my larger project... but I realize now those were due to other errors in my code - a reminder to myself to actually test things - this is the first time in four years I've done any programming so I am forgetting the basics...].
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.
Having such class can I instatiate it in place?
abstract class Mammal {
public abstract void Foo();
}
I expect that something like that should work:
Mammal wolf = new Mammal() {
public void Foo() { Console.WriteLine("Wooo"); }
}
However compilier doesn't allow that.
It looks like you're after something akin to an anonymous inner class in Java. There's no equivalent in C#. Options:
Create a nested class instead.
Create an implementation which uses delegates for each of the abstract methods, and then use anonymous functions to create those implementations "inline"
If the type consists of just a single abstract method, consider using a delegate instead of the abstract class to start with.
The very definition of abstract class is a class that cannot be instantiated. Here:
Use the abstract modifier in a class declaration to indicate that a
class is intended only to be a base class of other classes. Members
marked as abstract, or included in an abstract class, must be
implemented by classes that derive from the abstract class.
Having said that, it can have a constructor.
Your code does not make a lot of sense does not work in C#.
No, you can't do it.
See this reff
But you can inherit you own class:
public class ConcreetMammal : Mammal
{
public void Foo() {Console.WriteLine("Wooo");}
}
If you want to do this the closest I think you can get is to make Foo an Action and give Mammal a constructor that assigns a passed in function to Foo.
class Mammal {
public readonly Action Foo;
public Mammal(Action foo) { Foo = foo;}
}
...
...
var MyMammal = new Mammal(() => {Console.WriteLine("Wooo");});
Actually what Skeet was telling could be along these lines (great input as always)...
class Test
{
public delegate void MyFooSig();
public MyFooSig Foo { get; set; }
}
class Test1
{
public Action Foo { get; set; }
public Func<string, int, Test> MyOtherFoo { get; set; }
}
class Program
{
static void Main(string[] args)
{
var test = new Test
{
Foo = () => Console.Write("I'm in Foo"),
};
test.Foo();
var test1 = new Test1
{
Foo = () => Console.WriteLine("Foo via Action delegates"),
MyOtherFoo = (s, i) => new Test
{
Foo = () => Console.WriteLine("here it's me again..."),
},
};
test1.Foo();
test1.MyOtherFoo("", 1).Foo();
}
}
...not the same things though...
(note that's not inheritance, class is not abstract, it's more instantiating of one and the same)
plus there are dynamic objects - and you might want to take a look at Mock for C# for some ideas
Here's my best attempt to recreate the situation.
public interface IFoo
{
}
public class Foo : IFoo { }
public class Bar : IFoo { }
public class CollectionOf<T> : List<IFoo>
{
}
public class Bars : CollectionOf<Bar>
{
}
public class Test
{
public void Test()
{
CollectionOf<IFoo> bars = new Bars();
}
}
Compiler complains on the instantiation. Bars is a collection of IFoos. Is this one of those covariance/contravariance issues?
Yes.
Think about it for a second; bars should legally be able to hold objects of any type that implement IFoo. However, an object of type Bars can only hold objects of type Bar.
Using your code this would be allowed, which is obviously wrong.
CollectionOf<IFoo> bars = new Bars();
bars.Add( new Foo() ); // Uh oh!
That would effectively break the type safety afforded to you via generics.
Yes it is.
If this was allowed, you would be able to place any object into that collection, as long as it implemented the IFoo interface, but that wouldn't be safe for the collection.
Let me illustrate:
var b = new Bars();
CollectionOf<IFoo> bars = b;
bars.Add(Dummy); // implements IFoo, but does not descend from Bar
At this point, what does b contain? An object of type Dummy? That would be bad, and thus this is not allowed in the first place.
The fix, if there is one would depend on what it is that's not working for you. I can get your example to compile in two ways, either use IEnumerable or define your CollectionOf as an interface with the out generic modifier. Whether either is a fix for you I don't know:
public interface IFoo { }
public class Foo : IFoo { }
public class Bar : IFoo { }
public interface CollectionOf<out T> : IEnumerable<IFoo> { }
public class Bars : CollectionOf<Bar> { }
public class Test
{
public void Test()
{
IEnumerable<IFoo> bars1 = new Bars();
CollectionOf<IFoo> bars2 = new Bars();
}
}
Suppose I write a library with the following:
public class Bar { /* ... */ }
public class SomeWeirdClass<T>
where T : ???
{
public T BarMaker(Bar b)
{
// ... play with b
T t = (T)b
return (T) b;
}
}
Later, I expect users to use my library by defining their own types which are convertible to Bar and using the SomeWeirdClass 'factory'.
public class Foo
{
public static explicit operator Foo(Bar f)
{
return new Bar();
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
this will compile if i set where T : Foo but the problem is that I don't know about Foo at the library's compile time, and I actually want something more like where T : some class that can be instantiated, given a Bar
Is this possible? From my limited knowledge it does not seem to be, but the ingenuity of the .NET framework and its users always surprises me...
This may or not be related to the idea of static interface methods - at least, I can see the value in being able to specify the presence of factory methods to create objects (similar to the same way that you can already perform where T : new())
edit: Solution - thanks to Nick and bzIm - For other readers I'll provide a completed solution as I understand it:
edit2: This solution requires Foo to expose a public default constructor. For an even stupider better solution that does not require this see the very bottom of this post.
public class Bar {}
public class SomeWeirdClass<T>
where T : IConvertibleFromBar<T>, new()
{
public T BarMaker(Bar b)
{
T t = new T();
t.Convert(b);
return t;
}
}
public interface IConvertibleFromBar<T>
{
T Convert(Bar b);
}
public class Foo : IConvertibleFromBar<Foo>
{
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo> weird = new SomeWeirdClass<Foo>();
Foo f = weird.BarMaker(b);
}
}
edit2: Solution 2: Create a type convertor factory to use:
#region library defined code
public class Bar {}
public class SomeWeirdClass<T, TFactory>
where TFactory : IConvertorFactory<Bar, T>, new()
{
private static TFactory convertor = new TFactory();
public T BarMaker(Bar b)
{
return convertor.Convert(b);
}
}
public interface IConvertorFactory<TFrom, TTo>
{
TTo Convert(TFrom from);
}
#endregion
#region user defined code
public class BarToFooConvertor : IConvertorFactory<Bar, Foo>
{
public Foo Convert(Bar from)
{
return (Foo) from;
}
}
public class Foo
{
public Foo(int a) {}
public static explicit operator Foo(Bar f)
{
return null;
}
public Foo Convert(Bar b)
{
return (Foo) b;
}
}
#endregion
public class Demo
{
public static void demo()
{
Bar b = new Bar();
SomeWeirdClass<Foo, BarToFooConvertor> weird = new SomeWeirdClass<Foo, BarToFooConvertor>();
Foo f = weird.BarMaker(b);
}
}
Sounds like you found a solution to the larger problem. To answer your specific question: no, neither C# nor the CLR support the "backwards" generic type parameter constraint. That is,
class C<T> where Foo : T
"T must be Foo or a type which Foo converts to" is not supported.
There are languages that have that sort of constraint; IIRC Scala is such a language. I suspect this feature would be handy for certain uses of contravariant interfaces.
I don't think there is necessarily a syntactically cool way to do this built into the language. One possible solution to your problem could be to define a convertible interface:
public interface IConvertible<T>
where T : new() // Probably will need this
{
T Convert();
}
Then your class could be:
public class Foo : IConvertible<Bar>
{
}
I think this gets you close to where you want to be... All the Foo's and Bar's in your question sometimes make it hard to determine exactly what your intent is. Hope this helps.
Edit: Added where constraint... you will probably have to be able to create a new instance in your convertible class.
Edit 2: Made Foo inherit from ICovertible<Bar>
You could make a detour via an interface which is used as a type constraint.
For example, where T : IComparable<U> is used to constrain the type to something that can be compared to another thing, which must express this ability by implementing IComparable<another>. If you had an interface ICastableFrom<T>, you could achieve what you want by forcing them to implement ICastableFrom<Bar>.
Rather than go through the trouble of defining an interface and modifying your class to implement that interface, why not just do this?
public class SomeWeirdClass<T>
{
// aside: why is this method called 'BarMaker' if it returns a T?
public T BarMaker(Bar b, Func<Bar, T> converter)
{
// ... play with b
return converter(b);
}
}
Then in the event that you are dealing with an object of a type T to which Bar can be directly cast, this method could be called simply as follows:
var someWeirdObject = new SomeWeirdClass<Foo>();
var someBar = new Bar();
var someFoo = someWeirdObjcet.BarMaker(someBar, bar => bar as Foo);
By the way (since the Func<T, TResult> delegate emerged in .NET 3.5), you could also use Converter<TInput, TOutput> (which is exactly the same) for the converter parameter.