Replies: 40 comments 22 replies
-
From @dsaf on October 12, 2016 21:24 This seems to be a duplicate of #2206 which is a shame because your version is also well-written. On the upside it's already in |
Beta Was this translation helpful? Give feedback.
-
Ah :), well, my goal to get this implemented would still be resolved then. |
Beta Was this translation helpful? Give feedback.
-
From @dsaf on October 13, 2016 16:47 No idea. Let's say I wouldn't expect it next year. |
Beta Was this translation helpful? Give feedback.
-
From @timopomer on November 28, 2016 0:55 @devedse i know this issue is old, but just in case you wanted to make this you can use (R)Activator.CreateInstance(typeof(R), length) |
Beta Was this translation helpful? Give feedback.
-
Yeah, that's indeed one of the workaround you can use for now. However I would like to do this type safe at compile time :). |
Beta Was this translation helpful? Give feedback.
-
Well written Proposal. I would love to see this in the language. More compile time safety like this makes big codebases easier to maintain. |
Beta Was this translation helpful? Give feedback.
-
Some other potential solutions for this:
public interface IRandomFactory
{
IRandom Create(int length);
}
public struct FastRandomFactory : IRandomFactory //being a struct is important
{
public IRandom Create(int length) => new FastRandom(length);
}
public static IEnumerable<int> CreateRandomData<F>(int length)
where F : IRandomFactory, struct
{
var randomGenerator = default(F).Create(length);
for (int i = 0; i < length; i++)
{
yield return randomGenerator.Next();
}
}
public interface IRandom
{
public IRandom(int length);
...
} |
Beta Was this translation helpful? Give feedback.
-
The thing I'm worried about is that |
Beta Was this translation helpful? Give feedback.
-
Allowing interfaces to have static methods, or add new interfaces on types themselves could solve this. Create an instance of class just to call a method which returns new instance of this class. That's sounds weird. This is why we cannot have interface I know about implementation of generics with __Cannon so I don't have a good solution of how it could be implemented. However, we probably might add costructors to interfaces so I'd be: public interface ICreatable
{
string GetName();
new(string name);
} |
Beta Was this translation helpful? Give feedback.
-
@jnm2 shapes probably might solve this? I mean: public shape CreatableWithSeed
{
new(int seed);
}
public static IEnumerable<int> CreateRandomData<R>(int length)
where R : IRandom, CreatableWithSeed
{
var randomGenerator = new R(50);
for (int i = 0; i < length; i++)
{
yield return randomGenerator.Next();
}
} |
Beta Was this translation helpful? Give feedback.
-
This is part of a proposal being tracked at #110 which is under active development at MSR (Microsoft Research). |
Beta Was this translation helpful? Give feedback.
-
I don't recall ever having used new() without an additional type constraint. How does using new() without a type constraint have any more semantic meaning than using the theoretical or proposed parameterized new(...) without also using a type constraint? |
Beta Was this translation helpful? Give feedback.
-
It's common as part of a generic factory method (in the same spirit as
This is an excellent point. I would answer that it's obvious with You don't really have that question with |
Beta Was this translation helpful? Give feedback.
-
I don't see how that differs from what one must do today (use reflection to construct instances via calls to a parameterized constructor). This is widely done now, except that the construction is done via reflection, and the consumer of the class that performs the construction has to understand what the arguments of the constructor they have to provide mean. The only difference between that, and a parameterized new() constraint, is that it becomes a compile-time error rather than a runtime error. So, are you suggesting that what we must currently do today, we shouldn't do, because the meaning of the constructor's arguments aren't any more obvious than that of a parameterized new() constraint? One way or the other, it requires documentation. |
Beta Was this translation helpful? Give feedback.
-
@devedse considering how popular is this 10 year old question at stackoverflow, I would say it's not just "some people" ;) I personally consider it useful as I found myself more than once in need of a parameterized new() solution. My 2 cents. |
Beta Was this translation helpful? Give feedback.
-
Hi all, It's been a while, but I just saw a notification drop in my mailbox so I thought I'd chip in again too. I still think this idea would be great to add. As @Shadowblitz16 also mentioned, having this, simply makes sense. Having I saw your approach regarding shapes as well but I think this could still be a strong addition since shapes seem to resolve a more difficult challenge we're running into. In regards to @jnm2 's comment about it not having semantic meaning, can't we build it the same way that named tuple's solve this?:
That way you could have either one of these options: Option 1:
Option 2:
Another way I wouldn't mind this issue to be solved is by having the option to define a constructor definition inside an interface. I mean, why do we have the ability to define methods but not constructors? To me it would make sense to have both. This might also have some more benefits when doing serialization / deserialization. Option 3:
In my opinion, option 3 more closely follows the current C# spec. I think either one of these options could be implemented in a way that would avoid the use of Edit: Reference: #837 (comment) and #837 (comment) |
Beta Was this translation helpful? Give feedback.
-
It could be naturally solved if typeclasses come into the game so you can just write |
Beta Was this translation helpful? Give feedback.
-
@Pzixel then you'd still have the problem that it doesn't have any semantic meaning though. |
Beta Was this translation helpful? Give feedback.
-
I don't get your idea. Could you elaborate? It looks like it's a complete replacement: shape New<T> {
static Create(T arg) -> this;
}
...
void Foo<TVal, TNew>(Tval arg) where TNew : New<TVal>, IBar {
var newVal = TNew.Create(arg);
newVal.Bar();
} |
Beta Was this translation helpful? Give feedback.
-
Ah that's what you mean, I haven't really checked out shapes enough. So with that solution you wouldn't be using the constructor, but rather a static method that creates an instance of the class with some parameters? Could you maybe show an example how this would work for the example above with the Random instances? |
Beta Was this translation helpful? Give feedback.
-
No problem: public extension NewRandom of Random : New<int>
{
public static this Create(int arg) => new Random(arg);
}
public static IEnumerable<int> CreateRandomData<R>(int length) where R : IRandom, New<int>
{
var randomGenerator = R.Create(50);
for (int i = 0; i < length; i++)
{
yield return randomGenerator.Next();
}
} I'm also using a quite enhanced version of |
Beta Was this translation helpful? Give feedback.
-
@Pzixel, but in your example, why do you still include the |
Beta Was this translation helpful? Give feedback.
-
Because type inference in C# works this way (or to be more precise: it doesn't). |
Beta Was this translation helpful? Give feedback.
-
@devedse as I'm the one who "stirred the pot" I think that it might be better off if we keep the constructor in interface separate from the parametarized Now the question (IMHO always) is how can we draw some attention to this one so that it will have some chance to reach a future version of C#. C# 20 let's say -hope I wont be in pension by then.😅 As I see it, the popularity of the question in SO (where I actually landed this page from) can be an indicator of the usability of the feature. |
Beta Was this translation helpful? Give feedback.
-
Any updates on when could this be available in C#? |
Beta Was this translation helpful? Give feedback.
-
Let's step back a minute. The goal we're trying to achieve here is simple: at some point within the body of this function, we may want to create a new instance of Here's the original function using a callback instead:
(of course you could use Usage: Note that the end result doesn't even need to be generic. The function still has the ability to create a new instance of This is more flexible than the proposed generic constraint, doesn't require every implementer of IRandom to have a potentially breaking constructor, doesn't make use of reflection, doesn't require you to be the owner of every implementer, and is already fully supported. |
Beta Was this translation helpful? Give feedback.
-
Ok it seems I expressed the same need https://github.com/dotnet/runtime/issues/68858 |
Beta Was this translation helpful? Give feedback.
-
If the language had public void M<T>() where T : IFoo // instead of where T : new(...), now you have something with a specific meaning
{
T instance = T.Create(someSemanticInfo: 42);
// ...
}
// Having to declare the signature this way means that not all `new(int)`-shaped constructors are silently interchangeable
// regardless of what the parameters mean.
public interface IFoo
{
public static abstract this Create(int someSemanticInfo);
} |
Beta Was this translation helpful? Give feedback.
-
Here is a factory example using the static abstract interface methods in C# 11, that seems to be a useful workaround, continued from what @jnm2 mentioned. public interface IFactory<TSelf> where TSelf : IFactory<TSelf> {
static abstract TSelf New(int i, string s);
}
public struct Foo : IFactory<Foo> {
public static Foo New(int i, string s) {
return new Foo(i, s);
}
public readonly int I;
public readonly string S;
public Foo(int i, string s) {
I = i;
S = s;
}
}
public static class Maker {
public static T Make<T>(int i, string s) where T : IFactory<T> {
return T.New(i, s);
}
} But as @MithrilMan mentions, this only works if you are the owner of the target class. |
Beta Was this translation helpful? Give feedback.
-
From @devedse on October 12, 2016 20:20
Background
Currently C# allows its users to apply the "new()" constraint on methods accepting a generic type to let the compiler know it has a parameter-less constructor.
The following example shows 2 'random generators' that implement the IRandom interface that are being created and then used to return data:
Problem
Currently it's not possible to provide a parameter (e.g. a seed) to the constructor of the 'to-be created' random generators. The current solutions would be:
Solution: parameterized new()
My proposed solution would be to also accept parameter types in the new() constraint. E.g. the new(int) in the following line of code:
This would make the complete solution look something similar to this:
Copied from original issue: dotnet/roslyn#14461
Beta Was this translation helpful? Give feedback.
All reactions