Proposal: Named Constructors #1311
Replies: 15 comments 1 reply
-
How would named constructors be encoded in IL? How would you use named constructors from a language that doesn't support them (like F# or an older version of C#)? |
Beta Was this translation helpful? Give feedback.
-
Sounds like something better addressed via ADTs or DUs. |
Beta Was this translation helpful? Give feedback.
-
@HaloFour Would you mind expanding on that alphabet soup? |
Beta Was this translation helpful? Give feedback.
-
Algebraic Data Types or Discriminated Unions. Someone from a functional programming background could probably explain the details better than I, but in short it allows the definition of a data class represented by a set of named options. The use case illustrated above feels very similar to the That said, the use case is exceedingly simple to solve simply by defining the constructor as class CacheReadResult
{
public static CacheReadResultSuccess(object value) => new CacheReadResult(value, false);
public static CacheReadResultError(object sourceValue) => new CacheReadResult(sourceValue, true);
public object Value { get; }
public bool IsReadError { get; }
protected CacheReadResult(object value, bool isReadError)
{
Value = value;
IsReadError = isReadError;
}
}
class CacheReadResultWithMetadata : CacheReadResult {
public static CacheReadResultWithMetadata Success(object value, Metadata metadata) => new CacheReadResultWithMetadata(value, false, metadata);
public static CacheReadResultWithMetadata Error(object sourceValue, Metadata metadata) => new CacheReadResultWithMetadata(sourceValue, true, metadata);
public Metadata Metadata { get; }
protected CacheReadResult(object value, bool isReadError, Metadata metadata)
: base(value, isReadError)
{
Metadata = metadata;
}
} |
Beta Was this translation helpful? Give feedback.
-
I never heard this one before. 🤔 And the example you proceed to give is called the Factory Pattern, last I checked. |
Beta Was this translation helpful? Give feedback.
-
@Joe4evr It seems to be a C++ term for this... though only when the factory method is a part of the class being constructed. |
Beta Was this translation helpful? Give feedback.
-
When I see new CachedReadResult.Success(value) I think it looks like it's creating an instance of a nested type. Dart has this feature but I don't know if it has nested classes so maybe it doesn't look odd to Dart programmers. |
Beta Was this translation helpful? Give feedback.
-
with c# 7.2 you even have |
Beta Was this translation helpful? Give feedback.
-
@MkazemAkhgary |
Beta Was this translation helpful? Give feedback.
-
@aluanhaddad Could be |
Beta Was this translation helpful? Give feedback.
-
@aquartulli gotcha. I was just remarking on how it looks in Dart, but I understand it is the expressiveness and semantics that you want, not any specific syntax. |
Beta Was this translation helpful? Give feedback.
-
How would you disambiguate which named constructor to call in |
Beta Was this translation helpful? Give feedback.
-
@zippec Could add overloads to The I believe both of these solutions are backwards compatible in regard to these two issues. |
Beta Was this translation helpful? Give feedback.
-
This basically argues that current API / language constructs would not treat those methods as constructors. (What is left to differentiate them from factory methods?)
This means that adding named constructor could be a breaking change for the consumers of said class. |
Beta Was this translation helpful? Give feedback.
-
@zippec Your first point is only true with respect to solutions for that particular use case. You still get to use them as base constructors, and the other proposed solutions don't suffer from that problem. As for the second point, if you're using an existing, unnamed, parameterless constructor already and you add a new named constructor, then there's no ambiguity. It can prefer an unnamed, parameterless constructor (of which there can only be one) over a named parameterless constructor. I should have said "If there are multiple named, parameterless constructors and none have default then it doesn't fulfill the constraint. Conceptually, default is implicit on the namesless, parameterless constructor. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Right now AFAIK the solution to constructors that share signatures is to use the named constructor idiom:
This works fine until inheritance comes in. Even though CacheReadResult has two "public constructors", neither of them can be used as base constructors.
It would be nice to do something like this instead:
I'm aware that this is a particularly trivial example that has other simple solutions (like just making CacheReadResult's private constructor public and removing the static methods), but the point stands. In some cases I've encountered, the only solution is to put all parameters on the constructor and check that whatever arguments used are valid in combination. It works, but it's not very elegant and a compile-time solution would be nicer.
Beta Was this translation helpful? Give feedback.
All reactions