I'm writing a library that provides concrete implementations for interfaces at runtime using System.Reflection.Emit. The user should be able to write partially implemented interfaces without having the concrete types at hand.
I got most of it working, but there is a pain point with init setters which appears that it could almost be really neat. Because, interestingly, interface can have those:
public interface IFoo
{
String Name { get; init; }
}
Obviously this object can't be created directly:
var myFoo = new IFoo { Name = "Peter" }; // doesn't compile
They can, however be set within generics:
void SomeFunction(String name)
{
IFoo CreateFoo<CFoo>()
where CFoo : IFoo, new()
{
return new CFoo { Name = name };
}
// but what to do with CreateFoo now?
}
My question is now how this CreateFoo can be passed out of the function. As it stands, it's just a method group. Ideally, I want to create a delegate from it:
Delegate delegateOfMysteriousType = MakeSomeDelegate(CreateFoo);
Or some other kind of object implementing
interface Creator<I>
{
I Create<C>() where C : I, new();
}
But it seems that CreateMethod can't leave the method unless some concrete type is know to implement IFoo:
Delegate d = CreateFoo; // Cannot convert method group 'CreateFoo' to non-delegate type 'Delegate'
Object o = CreateFoo; // same
TakeTheDamnThing(CreateFoo); // Nothing will take this unless they already know a concrete IFoo
So it seems that it's impossible to transfer the information of CreateFoo out of the method unless one has, accessible from within the method, a concrete type implementing IFoo, which simply wont't exist at compile time.
If C# had classes nestable in function bodies with closure support, then the following would work:
public interface ICreator<I>
{
I Create<C>()
where C : I, new();
}
public void SomeFunction(String name)
{
public class FooCreator : ICreator<IFoo> // Error: attempt to write Java
{
public IFoo Create<C>()
where C : IFoo, new()
{
return new C { Name = name };
}
}
TakeTheDamnThing(new FooCreator()); // yay!
}
public void TakeTheDamnThing(ICreator<IFoo> creator); // No concrete type to be seen!
But since that's not a thing in C#, that won't work either.
So, my expectation is that this is indeed impossible, but I thought it worth putting it out to the community.
Any ideas?
Related
Let's assume I have an interface that has some method parametherized with another interface:
interface IFeature<T> where T : IFeatureParameters
{
CustomObject Apply(CustomObject obj, T featureParameters);
}
But features are so much different that there is nothing common in their parameters so IFeatureParameters interface is in fact marker interface. It just forces developers in future to create Feature and FeatureParameters implementations in pairs.
As far as I googled, marker interfaces are considered to have no reasons to exist in custom code.
Is it suitable to use marker interfaces in my case? If not, what may substitute it?
An interface IFeatureParameters has no added value here. Whether or not a class (or whatever type you like) is a valid type to pass parameters to a feature, is entirely determined by the feature implementation.
Every time a developer makes a new implementation of interface IFeature, they will specify explicitly what is the correct parameter type, by filling in the type variable T.
That is enough to ensure no 'alien' types will be passed into an implementation of method Apply.
Here is a simple example.
public class FeatureParametersA
{
public string SomeText;
}
public class FeatureParametersB
{
public int SomeNumber;
}
I could have made these classes implement an interface IFeatureParameters, but that is not required.
public interface IFeature<T>
{
CustomObject Apply(CustomObject obj, T par);
}
public class FeatureA : IFeature<FeatureParametersA>
{
public CustomObject Apply(CustomObject obj, FeatureParametersA par);
{
obj.Add(par.SomeText);
return obj;
}
}
public class FeatureB : IFeature<FeatureParametersB>
{
public CustomObject Apply(CustomObject obj, FeatureParametersB par);
{
obj.Add(par.SomeNumber.ToString());
return obj;
}
}
Notice how each class has its own dedicated implementation of Apply, specific for the related 'parameters' type.
Everything is strongly typed, so the compiler will prevent anyone from trying to pass the wrong type into Apply.
For completeness:
public class CustomObject
{
public void Add(string s) { _sb.AppendLine(s); }
private StringBuilder _sb = new StringBuilder();
}
Referencing to that Question: Cannot create an instance of the variable type 'Item' because it does not have the new() constraint
I would like to create an instance from a generic type with a non empty constructor.
public class A{};
public class B
{
public B(int){/*...*/}
}
public class C
{
public static T validate<T>(int index)
where T : A,
new(int) //error
{
if(/*validation*/)
return null;
return new T(index);
}
}
If I try to call B b = validate<B>(42); I got this error:
'B' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'C.validate(int)'
Question 1: Why can I use a parameterless constructors only?
Question 2: How can I solve my problem without delegates or interfaces?
(I am always looking for fancy solutions.)
Update for C# 11
The new static abstract/virtual members in interfaces feature, designed with generic maths in mind, but usable to require static factory functions for your type, is a great fit and I would recommend using it if you can change the type implementation.
Just add a static abstract T Create(your params come here...) to an interface, and then add a constraint in the form T : IYourInterface to your method.
Then, just use T.Create(...) to create an instance. Amazing, isn't it?!
Old Answer
You can use reflection to invoke the constructor:
var constructorInfo = typeof(T).GetConstructor(new[] { typeof(int) });
if (constructorInfo != null)
{
object[] parameters = new object[] { index };
return (T)constructorInfo.Invoke(parameters);
}
else
{
// handle it
}
(adapted from https://stackoverflow.com/a/13523659/5962841)
Or, you can use activator to create an instance (see #datrax's answer)
(T)Activator.CreateInstance(typeof(T), index)
The feature you asked for has already often been requested.
The request for the feature is being tracked here (github csharp design repo), but don't expect it this year, it's not even prototyped or accepted.
The problem here does not really lend itself to C# generics.
A generic type should have a common interface as far as properties & methods, that's the whole point of specifying T must be an instance of A or a subclass of A.
Here, A doesn't have an int constructor, but you want to create an instance of a subclass that does have an int constructor.
Also, from you code, B doesn't inherit from A, but you specified T: A in your generic method. Is that just an oversight?
Using Activator also relies on late binding, so if you call it for a class that doesn't have an appropriate constructor, you'll get a runtime error.
A functional approach is more intuitive, looks cleaner, and doesn't rely on runtime reflection.
public class A {
};
public class B:A
{
public B(int y){ x = y; }
public int x { get; }
}
public class C
{
public static T validate<T>(int index, Func<int, T> instantiator)
where T : A
{
if (false)
return null;
return instantiator(index);
}
}
class Program
{
static void Main(string[] args)
{
B b = C.validate<B>(42, (y)=>new B(y));
}
}
You are not allowed to pass any argument to the constructor of generic type. The only possible constraint is: where T :new ().
But anyway there's still a possibility to create such instance
(T)Activator.CreateInstance(typeof(T), index);
I saw a C# class SomeClass that was defined like
public class SomeClass : IComparable<SomeClass>, IEquatable<SomeClass>
{
// ...
}
and I'm wondering how to translate that into English. The way I understand it seems logically impossible. How can a class inherit from a parameterized version of itself? Also, is this a common design pattern?
The key is to recognize that it's not inheriting from (or implementing) a parameterized version of itself, but rather inheriting from (or implementing) another class or interface, and using itself as a generic parameter for that target type.
For example, IComparable<T> says that there will be a CompareTo() method that takes an object of type T as a parameter. So by implementing IComparable<SomeClass> you're simply guaranteeing that a method with that signature will exist on this class:
public class SomeClass : IComparable<SomeClass>
{
public int CompareTo(SomeClass other)
{
//...
}
}
And yes, this is fairly common practice. Classes often implement the generic IComparable<> and IEquatable<> interfaces to show that they can be compared with other items of the same type. It's maybe also worth mentioning that enums in Java are declared as extending Enum<> of themselves--a pattern which is not common in C#, but does appear from time to time.
Translated in "English" it means: "Boy (or girl), you'd better be type-safe when implementing those interfaces, especially IComparable. Otherwise, you'll have to perform type casting, which I guess you don't want"
See the code below. SomeClass implemented IComparable and IComparable.
See differencies between implementations of CompareTo(object) and CompareTo(SomeClass).
namespace InterfacesStuff
{
internal class Program
{
private static void Main(string[] args)
{
var someClass1 = new SomeClass {ComparedValue = 1};
var someClass2 = new SomeClass {ComparedValue = 2};
//someClassObject defined as SomeClass
//object someClassObject = new SomeClass { ComparedValue = 2 };
//someClassObject defined as anything else but SomeClass
object someClassObject = 5;
int comparisonSomeClassBySomeClass = someClass1.CompareTo(someClass2);
int comparisonSomeClassByObject = someClass1.CompareTo(someClassObject);
}
}
public class SomeClass : IComparable, IComparable<SomeClass>, IEquatable<string>, IEquatable<int>,
IEquatable<double>
{
public int ComparedValue;
public int CompareTo(object obj)
{
var presumedSomeClassObject = obj as SomeClass;
if (presumedSomeClassObject != null)
{
if (ComparedValue <= ((SomeClass) obj).ComparedValue)
return -1;
}
return 0;
}
public int CompareTo(SomeClass other)
{
if (ComparedValue <= other.ComparedValue)
return -1;
return 0;
}
public bool Equals(double other)
{
throw new NotImplementedException();
}
public bool Equals(int other)
{
throw new NotImplementedException();
}
public bool Equals(string other)
{
throw new NotImplementedException();
}
}
}
It is not Inheriting, It is implementing the IComparable Interface. what is going on is
Someclass Implements the Icomparable and the IEquatable interface. Implementing an interface is like signing a contract stating you gaurentee that this class will implement the methods on an interface.
Icomparable msdn, IEquatable. If you look at the MSDN pages you can see that SomeClass gaurentees it will implement the methods in some fashion.
This is very common practice and it is many different names. The ones I hear most are programming by contract and Implementation over Inhertience. It lets you do a lot of cool things, like Dependency Injection, Proper Unit testing, better Generics. It does this because the compiler doesnt need to know the concrete class that your object is implementing. It just needs to know that it has certain functions on it. For further reading on this I would read Chapter one of the gang of four Design pattern book.
Wikipedia link Specifically the Introduction to Chapter one section
It doesn't really have to be convenient to express it in english for it to be valid code, although I'd probably read that as "SomeClass is comparable and equatable to itself". That doesn't really explain what's going on though, it's just a way of expressing it.
In C# types can be generic over categories of other types. Generic types are basically "type constructors". They take other types as parameters, and use them to construct new types. For instance, IEnumerable<int> and IEnumerable<string> are two completely different types. The non-generic version (IEnumerable) is a third one. In C# a type A can inherit ANY other type B as long as none of the following is true (I hope I didn't miss anything):
B is already a subtype of A
B is a class and A has already inherited another class
B is a struct
A is an interface but B is not
A is the same type as B
B is sealed
A is a struct and B is not an interface
This even makes the following code legal:
class Foo<T>
{
public T Value;
}
class Foo : Foo<int>
{
}
Foo and Foo<T> are different types, so there's no problem at all for one to inherit the other.
You can read more about generics here:
https://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx
And about inheritance here:
https://msdn.microsoft.com/en-us/library/ms173149.aspx
The code you posted does not inherit from any class. It is implementing certain so-called Interfaces. How to translate that snippet: "I guarantee that SomeClass will be Comparable and equatable with other SomeClass instances. I will provide definitions in this class on how to do that."
About specializing a class from some other class...
What you can do is something like this:
using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
class Pet
{
protected string name;
public Pet(String name)
{
this.name = name;
}
}
class Dog : Pet
{
private List<String> tricks;
public Dog(String name, List<String> tricks):base(name)
{
this.tricks = tricks;
}
}
class Program
{
static void Main(string[] args)
{
List<string> tricks = new List<string>();
tricks.Add("sit");
tricks.Add("jump");
tricks.Add("bark");
Dog puppy = new Dog("Fido", tricks);
}
}
}
Dog inherits from Pet. Dog calls Pet's constructor at creation. Whatever name you pass into Dog constructor, it will forward it to Pet constructor.
Because what happens is that a subclass first calls the constructor of its superclass with the appropriate arguments. Then it runs its own constructor. Whatever is declared as public or protected in a class will be visible to its subclasses.
Therefore Dog will have name and also a list of tricks:
You achieve this kind of view with the "Locals" window.
I recommend that you read some tutorials on c# inheritance, interfaces and generics
I keep seeing this error, over and over again:
Cannot convert from Item<Foo> to Item<IFoo>.
This is clearly nonsense; an object of type Item<Foo> is statically guaranteed to be able to do absolutely everything that an Item<IFoo> can do (and possibly more), so why is the compiler refusing to accept my perfectly valid code?
I have a method that accepts an Item<IFoo> as an argument. For some reason, it refuses to accept an Item<Foo> as input, even though Foo implements IFoo. This makes no sense at all. I can pass a Foo in place of an IFoo, but I can't pass an Item<Foo> in place of an Item<IFoo>. Why?
public class Item<T>
{
public readonly int ID;
public readonly T Data;
...
}
public void ProcessItem(Item<IFoo> item)
{
Console.WriteLine(item.ID);
}
ProcessItem(new Item<Foo>());
Classes in C# are invariant, so depending on your requirements you'll have to create an interface and implment that:
public interface IItem<out T> { ... }
public class Item<T> : IItem<T> { ... }
IItem<IFoo> item = new Item<Foo>();
Note that it is not necessarily safe to assign a Class<Subtype> to a Class<Basetype>. A common example is List<T>:
List<object> l = new List<string>(); //won't compile
l.Add(3);
C# only allows variance annotations on interfaces and delegates, and only when it is safe to do so.
public abstract class A
{
// constructors omitted
public abstract A Create(SomeData data);
}
public class B : A
{
// constructors omitted
public override A Create(SomeData data)
{
return new B(data);
}
}
What I want is to be able to make the Create method static, so that I can get an instance of B without having to create a useless instance with an empty constructor. (If you're wondering why, A is actually a generic type of the form A<TFoo, TBar>, where TBar corresponds to the derived types. As we all know, you can't instantiate a generic type using a constructor that takes any arguments.)
I am already aware that static methods are decoupled from the object hierarchy, only relying on the name of the type. That means I can't have Create as an abstract method that I force all descendants to implement. Is there another way I can implement this pattern?
Something like this might work, depends on your requirements
public abstract class A
{
public string Data { get; set; }
public static T Create<T>(string data) where T : A, new()
{
return new T() { Data = data };
}
}
public class B : A { }
then can do
A foo = A.Create<B>("foo");
There is simply no way to do this. Inheritance is based off of instance methods in C# and has no equivalent feature for static methods. Another way to implement this pattern though is to require a lambda in lieu of a static method.
For example (you mentioned the actual type was A<TFoo, TBar>)
void UseIt<TFoo, TBar>(A<TFoo, TBar> p, Func<SomeData, TBar> func) {
TBar b = func();
...
}
The consumer doesn't care if Create is static, instance or even called create. Generally all they care about is having a function which takes a SomeData and returns a TBar. Delegates fit this pattern exactly.