0

Say I have a record as such:

public record myRecord(double count = -1);

Instead, I want to make the parameter variable an array of size 3 with its elements defaulted to -1, as such:

public record myRecord(double[]? count = {-1, -1, -1});

How do I do that? The above code throws the error "Default parameter value for must be a compile-time constant"

ks08
  • 84
  • 1
  • 9
  • And what exactly does the error message say? – Flydog57 Jul 11 '23 at 19:47
  • It has to be a compile time constant, right? – Fildor Jul 11 '23 at 19:48
  • 1
    This question [here](https://stackoverflow.com/questions/65978910/c-sharp-records-constructor-parameter-default-value-empty-ienumerable) asks almost the same about enumerable. The answer is the same tho. – Silvan Jul 11 '23 at 19:52
  • 2
    If you type it out this way: `public record MyRecord (double[] xxx = new[] {1.0, 2.0, 3.0} );`, you get the easy to understand: `error CS1736: Default parameter value for 'xxx' must be a compile-time constant`. By the way, `double[3]` is not a type, but `double[]` is. – Flydog57 Jul 11 '23 at 19:53

1 Answers1

1

Default parameter values must be compile-time constants. Arrays are not compile-time constants, so I think you'll have to specify the fields explicitly and provide a non-constant default value:

public record myRecord
{
    public double[] count = new double[] {-1, -1, -1};
}
D Stanley
  • 149,601
  • 11
  • 178
  • 240
  • 2
    `record` types are _meant to be_ immutable, but in this case using `public double[] count = ...` means you have a mutable field which itself contains an array with mutable elements. – Dai Jul 11 '23 at 20:37
  • @Dai Good point - OP should use `ReadOnlyCollection` instead if they want the array to be immutable. I also wonder if the built-in value-based comparisons will work automatically. – D Stanley Jul 11 '23 at 20:55
  • 2
    Don't use `ReadOnlyCollection`, it's an `class` adapter type (so it will incur GC allocation and introduce confusion about object-identity and ownership), instead we should all be using the _variant_ interfaces: `IReadOnlyList`, `IReadOnlyCollection`, or `IEnumerable` (in that order of preference). All .NET array types (`T[]`) implement `IReadOnlyList`. – Dai Jul 11 '23 at 20:56
  • @Dai, your solution does work; however, in this case I strictly want the variable to be passed in as a parameter to the record with chosen defaulted values. More like padeso's answer above – ks08 Jul 12 '23 at 11:47
  • @ks08 "my solution..." - I never offered-up any solution, I think you `@`-tagged the wrong person. – Dai Jul 12 '23 at 11:52
  • @Dai meant your suggestion* on using `IReadOnlyList`, apologies – ks08 Jul 12 '23 at 11:55
  • @ks08 What do you mean by "chosen defaulted values", exactly? – Dai Jul 12 '23 at 11:58
  • @Dai If you look at Padeos's answer above, his second method is what I'm aiming to do. All in all, I want to pass in an array to the record's param and have all of the elements in that array defaulted to a value. – ks08 Jul 12 '23 at 12:03
  • @ks08 If your array is non-null, why would you want to replace all of its member values? Or do you mean only when the parameter argument is `null`? – Dai Jul 12 '23 at 12:04
  • @ks08 Also, if your array is always going to have 3 elements then why bother using an array-type parameter at all? Just have 3 separate `double` parameters and have your `record` implement `IReadOnlyList`. – Dai Jul 12 '23 at 12:05
  • @Dai When I create a `myRecord` object, I want all of its parameters to have default values defined. One of the variable parameters for the record is an array (which holds lets say 10 signals). I want to default all of these signals in the array to a value, so if the user wants a new `myRecord` object, with no params specified, it gives them one with defaulted values. I just want a way to default the values in an array passed in as a parameter to a record. Hope this is clearer. – ks08 Jul 12 '23 at 12:16
  • 1
    Is there a reason you want to use a `record class` instead of a normal `class`? – Dai Jul 12 '23 at 12:20
  • @Dai For what I'm using it for, I am just storing data, which is what records are meant for. – ks08 Jul 12 '23 at 12:50
  • 1
    I think you're overstating the benefits or the stated-purpose of `record class` types - personally, I've found them to be incredibly compromised (because "immutable" (hah!) property-setters can still be invoked _after_ the ctor has run by using a C# object-initializer, which basically defeats the entire point of using a ctor to establish class-invariants. I suggest you stick to a good ol' fashioned `class` - yes, its' more tedious but it _will_ just-work. (The only USP that `record` types have is support for the `with` operator, but I've never found a use-case for it, YMMV). – Dai Jul 12 '23 at 13:01