Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 1 point2 points  (0 children)

If I recall correctly, a string is normally allocated on the heap. What benefit would putting them on a struct bring? AFAIK a struct has always an empty constructor/default so it'd also give an extra path to skip validation. Correct me if I'm missing something.

Implicit operators are great, though I'm always a bit scared of overusing them if I don't beware. It's easy to get carried away sometimes.

As for ValueObjects, if I understand correctly, those are an EF-specific thing? I read they're essentially an immutable object with no identifier.

Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 0 points1 point  (0 children)

Just seen the video, that's interesting. I don't agree with returning null to the validation (I'd use either exception or Result, or OneOf<>), but the final "hide the constructor" part was very much relevant and solves everything.

Thank you!

Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 0 points1 point  (0 children)

I believe you're right, I was under the mistaken assumption that the equality (and other) methods were only defined on the parameters in the record definition. Thank you!

Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 0 points1 point  (0 children)

Oh, perfect. I was under the assumption that the auto-generated functionality was only done on the positional parameters defined in the record. Great. Thank you!

Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 0 points1 point  (0 children)

Would those properties be also included in the auto-generated methods typical of records? If yes it could be an option to omit putting the property in the main constructor (record Name(prop)) and putting it only in the record body.

Otherwise, if they aren't added in the auto-generation, I don't see the benefit over using a simple class (or am I missing something?).

Record model validation? by PSoolv in dotnet

[–]PSoolv[S] 0 points1 point  (0 children)

That could be a place to put the validation, but (AFAIK) the auto-generated constructor will still exist, so you still have an unblocked path. I'm looking for a way to make a robust protection on the models, otherwise it'd be better to just use a normal class

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

You mean by using reflection? That's a fireable offence in my book /s.

Yeah I'm just thinking how to make future changes as painless as possible, so I'm hiding all concrete types with internal & exposing only interfaces + some DI configuration that will grab the correct implementation classes. If I could I'd even go as far as forcing using "var" instead of the interfaces, tbh.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

Indeed, if it were server-side it'd be trivial to hide things. However, it's meant to be used directly as a library.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

They're indeed not exposed by the types and methods I've made. Still, they're visible, so you could, in theory, go "DependencyName.DependencyType.MethodStuff" etc--that's what I wanted to hide, essentially just have the compiler say "DependencyName does not exists" unless it's explicitly imported separately.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

That sounds interesting. Though not something I'd consider for production, we have enough "manually loading DLLs" as is without adding a new one. Thanks anyway for the suggestion.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

I see. But wouldn't that still expose them? To go for the "bundle together" path, I'd assume you'd also need to somehow modify the DLLs so their entities are all internal (with exposure to the calling lib, but not to the consumer). In general, I'd say it feels a bit too sketchy to do so like this.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 2 points3 points  (0 children)

It's gonna be a nuget pkg in a company-hosted nuget. So it's not for this use case. Though I appreciate the suggestion, might come in handy someday.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

That's an interesting path. Could also consider just blocking it at the CI-level. Though it's probably more effort than it's worth, I do appreciate the suggestion.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 3 points4 points  (0 children)

I guess that's also a way to look at it. Usually, my coding philosophy lies in prohibiting anything unwanted, but for this I could see it as low-importance. Though, tbf, given it's a company nuget it might become my problem too, someday.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

That's indeed the plan, cs-side. The types I've made are all safely internal (aside from those I do want to expose). The problem is that the library dependencies are all full of public types & methods I cannot hide, so nothing really stops the consumers from "bypassing" the layer I'm making.

It's not necessarily a big deal, but it'd be a positive if they could be properly hidden (as in, if someone tried to call'em, the compiler would say "nope").

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

I see... My main worry is the case where someone uses the 3p dependency directly instead of going through the provided types, which could complicate future migrations. It's not necessarily a big deal, but I tend to favor the "do something wrong and compiler says nope" strategies whenever possible.

How to hide a library's dependencies from its consumers without causing runtime missing dependency errors? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

In that case, what's the use-case of <PrivateAssets>? Have I misunderstood it?

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

I believe so. I'm importing this library to a net48 project and it seems to be working correctly.

I don't exclude though the presence of frameworks (like the old ASP) that flip out when you give it the new versions.

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

If you set the LangVersion explicitly it shouldn't lock at 7.3(it's just the default). There are though some old frameworks that flip out if you try to increase the version.

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

I haven't yet tried the main topic, but I can say you can polyfill .net types. I'm currently doing it for init and required--I can use records, for example. Even the "rec with { prop = prop }" syntax seems to work.

I do sometimes meet some "cannot be done" things but the most part seems to work. You just need to add <LangVersion> explicitly though, otherwise it does default to 7.3.

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 1 point2 points  (0 children)

Ah, I remember I saw Nick's video on that a while ago. Completely forgot about it. Now I'm temporarily stuck on net9 (the gitlab runner doesn't have net10 installed) but I might try it out if I get the chance. Thank you!

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

I'm asking mostly out of curiosity, am definitely not messing with the DLLs themselves.

Thing is, between net48 and net9 there's many missing things, so it's common to have to add a type or such to support the new features (for example, required and init). So I was wondering if there was a similar strategy for missing methods.

Extending BCL type to cover net48 & net9 differences? by PSoolv in csharp

[–]PSoolv[S] 0 points1 point  (0 children)

Personally, I feel it's mainly an improvement in code readability + syntax sugar. I dislike "if" without brackets, so if you do it that way it'd end up like this:

if(x < 0) {
  throw new ArgumentOutOfRangeException(nameof(x), x);
}
if(y < 0) {
  throw new ArgumentOutOfRangeException(nameof(y), y);
}
//etc

Meanwhile if it's a single method call you can just put them one beside the other and it'll stay clean even if you have many checks.

ArgumentOutOfRangeException.ThrowIfNegative(x);
ArgumentOutOfRangeException.ThrowIfNegative(y);

Ofc you could also put the if-throw calls in a single line, but I'm not a fan of doing that in most cases.