Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exclude individual properties from the "Wither" #101

Open
bboyle1234 opened this issue Sep 20, 2019 · 7 comments
Open

Exclude individual properties from the "Wither" #101

bboyle1234 opened this issue Sep 20, 2019 · 7 comments
Labels

Comments

@bboyle1234
Copy link

Some immutable objects need to be able to exclude certain properties from the "Withing" feature.
Can there be an attribute added to a property that excludes it from the generation of With updaters?

@amis92
Copy link
Owner

amis92 commented Sep 20, 2019

@bboyle1234 I can't think of such a scenario. Why would just having the With available be a problem?

@amis92
Copy link
Owner

amis92 commented Sep 20, 2019

Because as far as I understand the question, everything would be as is, just the selected property's With method wouldn't be generated. Am I right?

@bboyle1234
Copy link
Author

Yes, you're right.
It's not strictly necessary to exclude the With method for that particular property, but it allows the developer to express intent clearly.
Let's take the good old stock market for example, and put together a stock's symbol and price in a record. The developer's intention is that this record be used for updating and distributing the price of a stock. The record is meant to have its price updated, but not the stock symbol. Here's how I'd want to code a record like that:

public sealed class StockPriceUpdate { 
  [SuppressWith] public string Symbol { get; }
  public decimal Price { get; }
}

@amis92
Copy link
Owner

amis92 commented Sep 20, 2019

Currently, it doesn't make sense (the request): there are other ways to instantiate the copy with symbol changed, e.g. constructor, builder, Update method. A comment should pass the intent "enough".

In this scenario, the class isn't really a record: It has some constraints that disqualify it, like disallowing mutation of some property. You'd also probably want to hide the constructor as internal, disable Builder, hide the Update. Overall, it seems like too much work to even use the Record.

In terms of benefitting from Equality etc. (I suppose it's a feature that could make this customization effort worth marking this class as Record), I start to think that we should build a palette of different generators, and equality/comparisons are great candidates to separate them out.

@bboyle1234
Copy link
Author

Yes.
Like everyone, I'm very much looking forward to the legendary c# 8.0 records feature.
But not because I want records. It's because I want to work with immutability and memberwise equality without too much boiler plate code.
This project, though it's named "record" and attempts to be records, is actually the best library I have found for what I (and all the other developers) really need -- a proper library for efficiently implementing immutability and memberwise equality.

It's very tempting to limit the scope of this project to "just records" because that's a lot narrower and simpler. But what we all really need is a library that allows us to write flexible immutable classes.

@bboyle1234
Copy link
Author

It would be really cool if this project would allow setting the publicity of the builders, constructors, etc to something other than public.

I've seen this done in AArnott's ImmutableObjectGraph library.

Other things I really liked from that library were the ability to pre-calculate the hashcode just once, in the constructor, and I especially like the convention of using readonly fields instead of readonly properties.

That's because when writing immutable objects, we often don't want to expose all the readonly fields as public properties, or we want to expose properties that are formed differently from the underlying readonly fields.

@amis92
Copy link
Owner

amis92 commented Sep 20, 2019

It would be really cool if this project would allow setting the publicity of the builders, constructors, etc to something other than public.
I've seen this done in AArnott's ImmutableObjectGraph library.

I'm lazy. Can you summarize how it was done?

Other things I really liked from that library were the ability to pre-calculate the hashcode just once, in the constructor, and I especially like the convention of using readonly fields instead of readonly properties.

I'm a strong supporter of properties, because they offer a much better extensibility approach, are more concise, were designed for publicly exposing "data" members (not methods) and have superior tooling support in a staggering number of scenarios. Fields are much simpler indeed. That'd be their only advantage.

That's because when writing immutable objects, we often don't want to expose all the readonly fields as public properties, or we want to expose properties that are formed differently from the underlying readonly fields.

That might be true, but in that case - most of this library's features are useless. What's left? Constructor? How would Builders or Withers work if there's no ctor params <-> backing fields <-> properties parity? Equality is a recent addition, and I'm more and more convinced it should be extracted into a separate library. It's undeniably useful, and in more scenarios than records are. "Primary" constructor would be another candidate, so it'd fulfill the need for a more customizable feature set, like accessibility, additional extension points, readonly fields support, etc.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants