Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
mystes
May 31, 2006

power crystals posted:

But those things worked just fine when it was only Framework, it was the introduction of Core specifically that broke everything. So surely in our brave Core-only future they could continue to work fine even ignoring Standard by doing what they used to do. Even Microsoft's own .NET 5 announcement post has them wondering "Do we still need .NET Standard?".
They clearly don't now.

Adbot
ADBOT LOVES YOU

Boz0r
Sep 7, 2006
The Rocketship in action.

Mongolian Queef posted:

Can you clarify a bit?

The following is how many of our apps is structured:

MyProductName/MyProductName.sln
MyProductName/DAL/DAL.csproj
MyProductName/UI/UI.csproj
MyProductName/Application/Application.csproj

And so on. Do you mean they are kept separate in some other way?

Like all our solutions are put one place and all our code in a completely different place like so:

\Solutions\Product\Sub-Product\Sub-Product.sln
\Trunk\Product\Sub-Product\

Mongolian Queef
May 6, 2004

Boz0r posted:

Like all our solutions are put one place and all our code in a completely different place like so:

\Solutions\Product\Sub-Product\Sub-Product.sln
\Trunk\Product\Sub-Product\

I see. Yeah, I have no idea why that would be a thing to do either.

LongSack
Jan 17, 2003

Cuntpunch posted:

Maybe I'm missing something in your description, but why not just break out the grids into their own controls that you swap in as necessary?

Good idea! Thanks.

Edit: This worked really well. Split the properties, commands, command methods, utility methods out into separate view models for each control. The MainViewModel is now much more manageable (i can recombine the 5 separate files back into a single file now, if I choose).

Only side effect is that the designer is throwing an error about not being able to locate my appsettings.json file. The app still runs, so it must be a designer issue (it's looking in the Visual Studio IDE directory).

LongSack fucked around with this message at 19:59 on Nov 14, 2019

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

mystes posted:

They clearly don't now.

.NET Core 5 still won't support all the platforms that Mono does, will it?

If it needs to coexist with Mono for a few years yet, there's still value in having a common interface for library maintainers to code against. If they stop updating .NET Standard, then they should at least allow mono{versionNumber} as a valid string in the <TargetFrameworks> project element.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Boz0r posted:

Like all our solutions are put one place and all our code in a completely different place like so:

\Solutions\Product\Sub-Product\Sub-Product.sln
\Trunk\Product\Sub-Product\

I can't think of a single problem that solves. Weird.

ljw1004
Jan 18, 2005

rum

Mongolian Queef posted:

I see. Yeah, I have no idea why that would be a thing to do either.

In several teams at Microsoft, most .sln files are generated programmatically and are local to the developer's own machine; they don't get checked into source control. E.g. I want to work on a feature that cross-cuts between two projects, so I generate a .sln that references these two projects as source, and references the other sixty projects as binary DLLs, and VS loads a lot quicker. Maybe this company's policy originated with something like this? and they felt squeamish about storing generated files in the same directory as source-controlled files?

Boz0r
Sep 7, 2006
The Rocketship in action.
What's a good tool for generating proxy classes based on http controllers?

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
(Crossposted from general programming thread)

I'm trying to roll my own pubsub system in C#, mostly because I thought it'd be pretty straightforward. But making it clean (i.e. not having a million little subscribe/unsubscribe functions for each individual event type) is proving a little trickier than I'd thought it'd be. I have this class:
code:
public interface IPubsubEvent {}

public class PubSub {

    private class SubscriberSet<T> : HashSet<Action<T>> where T : IPubsubEvent { }

    private static Dictionary<Type, SubscriberSet<IPubsubEvent>> subscribers = new Dictionary<Type, SubscriberSet<IPubsubEvent>>();
    public static void Subscribe<T>(Action<T> callback) where T: IPubsubEvent {
        var typ = typeof(T);
        if (!subscribers.ContainsKey(typ)) {
            subscribers[typ] = new SubscriberSet<IPubsubEvent>();
        }
        subscribers[typ].Add(callback);
    }
    public static void Unsubscribe<T>(Action<T> callback) where T: IPubsubEvent {
        var typ = typeof(T);
        var cb = callback as Action<IPubsubEvent>;
        if (!subscribers.ContainsKey(typ) || !subscribers[typ].Contains(cb)) {
            throw new System.Exception("Action " + callback + " not subscribed.");
        }
        subscribers[typ].Remove(cb);
    }
    public static void Publish<T>(T e) where T: IPubsubEvent {
        if (!subscribers.ContainsKey(typeof(T))) {
            // Nobody to publish to.
            return;
        }
        foreach (var f in subscribers[typeof(T)]) {
            Debug.Log("Invoking " + f + " on " + e);
            f(e);
        }
    }
}
I'm getting an error at the Add statement in Subscribe: "cannot convert from System.Action<T> to System.Action<PubsubEvent>". Which is strange, because the function has a constraint on it that T must be a PubsubEvent. Any idea what's going on here?

AskYourself
May 23, 2005
Donut is for Homer as Asking yourself is to ...

Boz0r posted:

What's a good tool for generating proxy classes based on http controllers?

For c# core, we’ve been using Nswag Studio with acceptable results https://github.com/RicoSuter/NSwag/wiki/NSwagStudio

No Pants
Dec 10, 2000

TooMuchAbstraction posted:

I'm getting an error at the Add statement in Subscribe: "cannot convert from System.Action<T> to System.Action<PubsubEvent>". Which is strange, because the function has a constraint on it that T must be a PubsubEvent. Any idea what's going on here?

The type parameter of Action<T> is contravariant, not covariant (i.e. you may assign an instance of Action<TBase> to a variable of Action<TDerived>, but not the other way around). Read more about this here.

Without saying anything about your design, to get this to compile, store the delegates as plain objects and cast them to Action<T> in your Publish method.

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe

No Pants posted:

The type parameter of Action<T> is contravariant, not covariant (i.e. you may assign an instance of Action<TBase> to a variable of Action<TDerived>, but not the other way around). Read more about this here.

Without saying anything about your design, to get this to compile, store the delegates as plain objects and cast them to Action<T> in your Publish method.

Thanks! Jabor gave a similar response in the General Programming thread. It's unfortunate, but the type-unsafety is kept to a small part of the code so I guess I can live with it.

If you'd care to, I'm curious what your opinions are about the design.

No Pants
Dec 10, 2000

TooMuchAbstraction posted:

Thanks! Jabor gave a similar response in the General Programming thread. It's unfortunate, but the type-unsafety is kept to a small part of the code so I guess I can live with it.

If you'd care to, I'm curious what your opinions are about the design.

Without knowing more, there doesn't seem to be a need for any of PubSub's members to be static. Storing your state in an instance of your service would let the programmer decide how global that state should be, and it would be easier to test.

Having a delegate object be the identity of a subscription is a little suspect, especially when you're storing them in a HashSet<>. You'll need to be conscious of delegate equality and think about edge cases.

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
Good points both, thank you.

LongSack
Jan 17, 2003

a hot gujju bhabhi posted:

What if a separate instance of the app has mutated that entity in the meantime?

As a follow up to this, EF Core (not sure about EF 6) makes this pretty easy.

Add a member to your entity classes (I call it RowVersion, which is what the Microsoft docs use) and decorate it with the [Timestamp] attribute. EF will then use that member in a WHERE(...) clause for updates and deletes.

So if some other user updates a row, the RowVersion will be updated, the WHERE(...) clause will fail, EF will detect that 0 rows were updated when 1 was expected, and it throws a DbUpdateConcurrencyException that you can catch and handle as you see fit.

The only wrinkle was that I need to copy the updated RowVersion from the entity into my DTO post-update, just like I copy the Id post-insert. Works quite well.

RICHUNCLEPENNYBAGS
Dec 21, 2010
After dealing with various EF-related bullshit I've been radicalized into preferring Dapper. Feels like you get rid of one small headache at the expense of three less obvious ones that are harder to deal with.

EssOEss
Oct 23, 2006
128-bit approved
I went down that road for a while but eventually concluded that I was overreacting and that EF is pretty great as long as you constrain yourself to the small subset of features where you just use it as a better-designed "data table reader" API. All the object modeling proxy lazy loading relationship stuff is bullshit. But just for reading & writing rows in tables it is really awesome and the composability of the queries is often good (I can't say great, given how many EF bugs I have reported on query construction).

The drawback in Dapper that I found was that it did the mapping to objects well but nothing quite so much around it. Does it nowadays do updates, writes and proper query composition? It was way too barebones and read-oriented for my taste when I last touched it a year or two ago, even with the IQueryable stuff in the Contrib package.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

TooMuchAbstraction posted:

(Crossposted from general programming thread)

I'm trying to roll my own pubsub system in C#, mostly because I thought it'd be pretty straightforward. But making it clean (i.e. not having a million little subscribe/unsubscribe functions for each individual event type) is proving a little trickier than I'd thought it'd be. I have this class:
code:
...
I'm getting an error at the Add statement in Subscribe: "cannot convert from System.Action<T> to System.Action<PubsubEvent>". Which is strange, because the function has a constraint on it that T must be a PubsubEvent. Any idea what's going on here?

No Pants made some good points already. The first point I would add is that you might want to look at the Observable<T> type from the Reactive Extensions library, if you haven't already. It does the same thing as your PubSub class except that it's tied to a particular delegate type. I think some of the problems you're having with your design stem directly from trying to accommodate different delegate types in the same mapping, and I'm not too sure what it affords you. Instead of having a single PubSub object where you can pass any delegate type, I would turn PubSub into PubSub<T>, and have one each per input delegate type. If you really need it you could have another abstraction above that that orchestrates different PubSub<T> instances.

Your class exhibits some non-obvious behavior because it uses the delegate type as its dispatch mechanism. If I have the classes Animal and Giraffe (with class Giraffe : Animal, of course) and I subscribe with an Action<Animal> and then publish a Giraffe, my delegate won't be called even though it's capable of handling giraffes, since only delegates of type Action<Giraffe> are considered. I think many would find this surprising, although others may consider it correct. In any case it's a corner case that would go away if your class was instead PubSub<T>, because you then wouldn't need to do any type checking when dispatching to the observers. If you want to keep your current design but support delegate type inheritance you could use the Type.IsAssignableFrom method instead of comparing equality, but then you'd lose the benefits of using a Dictionary since you would have to iterate through the whole thing every time.

What does the IPubsubEvent interface do for you? It forces code that wants to use the PubSub class to decorate its event classes with that interface, but it doesn't seem to add any real type safety or features. Empty interfaces are rarely necessary. I believe you should remove it and just operate on Action<object> internally (or, if your class is PubSub<T>, you can use Action<T> everywhere).

On the subject of delegate equality, while you can't avoid this problem entirely, you can minimize the problem by generating a unique ID for each delegate and putting that in the dictionary instead of the actual Action. In addition to that you can implement unsubscription by having the Subscribe method return an "unsubscriber" object that you can call on demand. In the Observable class this is done with a totally featureless object that implements IDisposable, but you could use a custom Subscription object that has other methods on it as well.

(Note: These code examples are untested and probably not fully thought through.)

C# code:
public class PubSub
{
    private readonly Dictionary<Subscriber, SubscriberSet<IPubsubEvent>> subscribers;

    public IDisposable Subscribe<T>(Action<T> observer)
    {
        // One downside is that this has now become an O(n) operation.
        var existing = subscribers.SingleOrDefault(s => s.Observer ==observer);
        if (existing == null)
        {
            var subscriber = new Subscriber(Guid.NewGuid(), observer);
            subscriptions.Add(subscriber);
            return new Unsubscriber(subscriber, this);
        }
        else
        {
            return new Unsubscriber(existing, this);
        }
    }

    private void Unsubscribe(Subscriber subscriber) // This method is private since the caller doesn't know the Subscriber class exists.
    {
        // ...
    }

    private class Subscriber
    {
        // this class should implement IEquatable<Subscriber> with the Guid as its identity
        public Subscriber(Guid id, Action observer) { ... }
    }

    private class Unsubscriber : IDisposable
    {
        private readonly Subscriber subscriber;
        private readonly PubSub pubSub;

        public Unsubscriber(Subscriber subscriber, PubSub pubSub)
        {
             this.subscriber = subscriber;
             this.pubSub = pubSub;
        }

        public void Dispose() => pubSub.Unsubscribe(subscriber); // This is what the caller uses to unsubscribe.
    }
}
If you've turned PubSub into PubSub<T>, Subscriber and Unsubscriber could also be made generic.

Even though you still have to compare delegates for equality, the design now leads callers away from making mistakes like this:

C# code:
class Example : IDisposable
{
    public void SomeMethod(ExampleEvent e) { ... }

    public void Subscribe() => this.pubSub.Subscribe(e => SomeMethod(e));

    public void Dispose() => this.pubSub.Unsubscribe(e => SomeMethod(e)); // Not the same delegate!
}
The above example would actually work as intended if you used Subscribe(SomeMethod) and Unsubscribe(SomeMethod) instead, but in my experience a lot of people don't realize that you can pass around method groups directly like that. With the unsubscriber object you're forced to do this instead:

C# code:
class Example : IDisposable
{
    public void SomeMethod(ExampleEvent e) { ... }

    public void Subscribe() => this.subscription = this.pubSub.Subscribe(SomeMethod); // Doesn't matter if you do SomeMethod or e => SomeMethod(e) here.

    public void Dispose() => this.subscription.Dispose();
}
One final point is that your PubSub class lacks thread-safety. If one thread adds a subscription while another removes one you can easily end up with unhandled exceptions from inside the Dictionary class because the internal data structures will be read and modified simultaneously. This can be mitigated by using ConcurrentDictionary, but you would still have threading issues within the Subscribe method, especially with the change I've suggested. Since this is a general purpose class that people would expect to be thread-safe, you should probably add locking to make sure all the possible combinations of concurrent calls to Subscribe/Unsubscribe/Publish work as one would expect.

Boz0r
Sep 7, 2006
The Rocketship in action.
I've begun generating proxies with swagger -> NSwag for some of our web services and I've hit a small snag. We have our own common DTOs, and we'd like to reuse them in the proxy calls. Is this possible, and how?

EDIT: I got it working except for lists of DTOs, then it just generates a list of object.

Boz0r fucked around with this message at 12:29 on Nov 25, 2019

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

Boz0r posted:

I've begun generating proxies with swagger -> NSwag for some of our web services and I've hit a small snag. We have our own common DTOs, and we'd like to reuse them in the proxy calls. Is this possible, and how?

EDIT: I got it working except for lists of DTOs, then it just generates a list of object.

NSwag has always handled collection types as arrays just fine, in my experience*. Are you annotating the methods with the SwaggerProduces attribute (assuming they don't already have the 200 OK payload as the return type)?

* Other than a hilarious accident which was totally my fault, where I injected an OpenApiProcessor to publish F# union types as OpenAPI oneOf composite types, and all the linked lists suddenly became published as a union of nil and cons - I had fun explaining that to the Java programmer who was consuming that API.

NihilCredo fucked around with this message at 20:38 on Nov 25, 2019

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION
I'm looking at migrating some of our ancient horseshit code to .NET Core, especially since EntityFramework supports .NET Core 3.0. This has gone surprisingly well so far, but the wrinkle I've hit is the Microsoft.AspNet.Identity.EntityFramework stuff. The IdentityDbContext etc. I can't find a .NET Core equivalent of it that works with EntityFramework (as opposed to EF Core). Does anyone know anything about this at all? I admit I'm a bit lost.

mystes
May 31, 2006

Someone who's apparently a Microsoft employee made this nice cross platform desktop (windows/mac/linux) webview wrapper type thing for .net core: https://github.com/SteveSandersonMS/WebWindow

It's not production quality yet, and obviously compared to something like electron there are going to be more issues with things displaying different on different platforms, but it has built in support for server side blazor and it's very easy and fun to mess around with.

mystes fucked around with this message at 02:35 on Nov 26, 2019

EssOEss
Oct 23, 2006
128-bit approved

a hot gujju bhabhi posted:

I'm looking at migrating some of our ancient horseshit code to .NET Core, especially since EntityFramework supports .NET Core 3.0. This has gone surprisingly well so far, but the wrinkle I've hit is the Microsoft.AspNet.Identity.EntityFramework stuff. The IdentityDbContext etc. I can't find a .NET Core equivalent of it that works with EntityFramework (as opposed to EF Core). Does anyone know anything about this at all? I admit I'm a bit lost.

I believe legacy ASP.NET Identity supports legacy Entity Framework. And ASP.NET Core Identity supports EF Core. To migrate to EF Core, you also need to migrate to ASP.NET Core.

In general, you should not think of anything "Core" as a different implementation of the same thing. It is a completely standalone library/framework that just happens to be named after another library/framework produced by the same company and maybe follows some similar general principles. You can't just mix and match Core and non-Core.

AskYourself
May 23, 2005
Donut is for Homer as Asking yourself is to ...

Boz0r posted:

I've begun generating proxies with swagger -> NSwag for some of our web services and I've hit a small snag. We have our own common DTOs, and we'd like to reuse them in the proxy calls. Is this possible, and how?

EDIT: I got it working except for lists of DTOs, then it just generates a list of object.

Not sure if I understand your issue but maybe automapper could help

RICHUNCLEPENNYBAGS
Dec 21, 2010

EssOEss posted:

I went down that road for a while but eventually concluded that I was overreacting and that EF is pretty great as long as you constrain yourself to the small subset of features where you just use it as a better-designed "data table reader" API. All the object modeling proxy lazy loading relationship stuff is bullshit. But just for reading & writing rows in tables it is really awesome and the composability of the queries is often good (I can't say great, given how many EF bugs I have reported on query construction).

The drawback in Dapper that I found was that it did the mapping to objects well but nothing quite so much around it. Does it nowadays do updates, writes and proper query composition? It was way too barebones and read-oriented for my taste when I last touched it a year or two ago, even with the IQueryable stuff in the Contrib package.

No, it's very barebones, but Rider will do SQL autocomplete when it detects you're writing a query, which makes it pretty painless IMO. I'm pretty happy with it just handling materializing the objects based on my queries and nothing else. If you're using EF the right way you're probably writing various projections and stuff anyways, which isn't really less complicated.

LongSack
Jan 17, 2003

Anyone know of a good folder picker dialog for WPF running on .NET Core 3.0? I normally use the CommonOpenFileDialog (I think that’s the name) from the Microsoft.WindowsApiCodePack.Shell package (again, I think that’s the name), but it targets .NET Framework.

I suppose I could roll my own, but if there’s already a good one out there, I can save the time and effort.

TIA

Boz0r
Sep 7, 2006
The Rocketship in action.
I have a function that takes a bunch of reference types, and none of them can be null. Right now it checks them all and throws an exception if one is null, but it seems really unnecessary.

code:
void Function(string param1, string param2, string param3, string param4, string param5,
            string param6, string param7, string param8)
        {
            if (string.IsNullOrEmpty(param1)) throw new ArgumentNullException(nameof(param1));
            if (string.IsNullOrEmpty(param2)) throw new ArgumentNullException(nameof(param2));
            if (string.IsNullOrEmpty(param3)) throw new ArgumentNullException(nameof(param3));
            if (string.IsNullOrEmpty(param4)) throw new ArgumentNullException(nameof(param4));
            if (string.IsNullOrEmpty(param5)) throw new ArgumentNullException(nameof(param5));
            if (string.IsNullOrEmpty(param6)) throw new ArgumentNullException(nameof(param6));
            if (string.IsNullOrEmpty(param7)) throw new ArgumentNullException(nameof(param7));
            if (string.IsNullOrEmpty(param8)) throw new ArgumentNullException(nameof(param8));
...
}
I was thinking of making a function that took an array of objects and checked them but then I'd lose the parameter names. Any ideas?


AskYourself posted:

Not sure if I understand your issue but maybe automapper could help

I got it working, the list of objects was a weird bug and since then, all the lists have been the correct DTOs.

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

EssOEss posted:

I believe legacy ASP.NET Identity supports legacy Entity Framework. And ASP.NET Core Identity supports EF Core. To migrate to EF Core, you also need to migrate to ASP.NET Core.

In general, you should not think of anything "Core" as a different implementation of the same thing. It is a completely standalone library/framework that just happens to be named after another library/framework produced by the same company and maybe follows some similar general principles. You can't just mix and match Core and non-Core.

Yeah sorry, I get that. But the old entity framework was recently ported to .NET core, so suddenly you can upgrade to .NET Core 3 with very few changes. But the identity side doesn't seem to have been ported.

brap
Aug 23, 2004

Grimey Drawer

Boz0r posted:

I have a function that takes a bunch of reference types, and none of them can be null. Right now it checks them all and throws an exception if one is null, but it seems really unnecessary.

code:
void Function(string param1, string param2, string param3, string param4, string param5,
            string param6, string param7, string param8)
        {
            if (string.IsNullOrEmpty(param1)) throw new ArgumentNullException(nameof(param1));
            if (string.IsNullOrEmpty(param2)) throw new ArgumentNullException(nameof(param2));
            if (string.IsNullOrEmpty(param3)) throw new ArgumentNullException(nameof(param3));
            if (string.IsNullOrEmpty(param4)) throw new ArgumentNullException(nameof(param4));
            if (string.IsNullOrEmpty(param5)) throw new ArgumentNullException(nameof(param5));
            if (string.IsNullOrEmpty(param6)) throw new ArgumentNullException(nameof(param6));
            if (string.IsNullOrEmpty(param7)) throw new ArgumentNullException(nameof(param7));
            if (string.IsNullOrEmpty(param8)) throw new ArgumentNullException(nameof(param8));
...
}
I was thinking of making a function that took an array of objects and checked them but then I'd lose the parameter names. Any ideas?


I got it working, the list of objects was a weird bug and since then, all the lists have been the correct DTOs.

You could thumbs up this language proposal and then wait probably a year: https://github.com/dotnet/csharplang/issues/2145

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

brap posted:

You could thumbs up this language proposal and then wait probably a year: https://github.com/dotnet/csharplang/issues/2145

Or start transitioning to nullable reference types. The best way to not have to do null checks it to have the compiler enforce that a value can't be null.

Boz0r
Sep 7, 2006
The Rocketship in action.

New Yorp New Yorp posted:

Or start transitioning to nullable reference types. The best way to not have to do null checks it to have the compiler enforce that a value can't be null.

We've only begun transitioning some of our projects to Core, and this ain't one of them.

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings

Boz0r posted:

We've only begun transitioning some of our projects to Core, and this ain't one of them.

The feature is language-level, being part of C# 8, which is supported by Framework 4.8.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
The VS UI can make it look like you can only use non-nullable with Core, but you can easily do it with 4.8 projects by editing the csproj file manually. Just add this to the main PropertyGroup:
code:
    <LangVersion>8.0</LangVersion>
    <Nullable>enable</Nullable>
With that said...

New Yorp New Yorp posted:

Or start transitioning to nullable reference types. The best way to not have to do null checks it to have the compiler enforce that a value can't be null.

It's worth noting that the non-null guarantees are quite a bit weaker than other type mismatches. Here are some of the ways a variable could be null even though you're in a non-nullable context and it's not marked as nullable:

1. The variable was created in a non-nullable context and then passed to your method, e.g. from another project without Nullable=enable, a .NET Framework method, some third party library, a part of your code where you temporarily disabled non-nullable, etc.
2. Someone used the exclamation point operator to assert that the variable was non-null, even though it was null.
3. Tricks involving reflection/dynamic.

Some of this will get better as .NET APIs and other libraries are updated to support non-nullable reference types.

For those reasons I've found that some code, mostly public methods in projects that are referenced by other projects, should still do null checks even with Nullable=enable. But I by no means want to discourage people from enabling it. It's great!

Nth Doctor
Sep 7, 2010

Darkrai used Dream Eater!
It's super effective!


New Yorp New Yorp posted:

Or start transitioning to nullable reference types. The best way to not have to do null checks it to have the compiler enforce that a value can't be null.

I attended a 20 minute session on this at Ignite, and still can't get my head around who thought

code:
static int GetMiddleNameLength() {
  if(person.middleName is {} middle) {
    return middle.Length;
  }
  else {
    return 0;
  }
}
was a good syntax choice.

redleader
Aug 18, 2005

Engage according to operational parameters
i've never seen that is {} middle syntax before with that curly brackets... got a relevant link?

LongSack
Jan 17, 2003

Nth Doctor posted:

I attended a 20 minute session on this at Ignite, and still can't get my head around who thought

code:
static int GetMiddleNameLength() {
  if(person.middleName is {} middle) {
    return middle.Length;
  }
  else {
    return 0;
  }
}
was a good syntax choice.

Never seen that syntax. I think I’d use

C# code:
 int GetMiddleNameLength() => person?.middleName?.Length ?? 0;

mystes
May 31, 2006

I really don't get it . What's the advantage of abusing property pattern syntax like this instead of just writing "string"? It can't even handle person being null.

rarbatrol
Apr 17, 2011

Hurt//maim//kill.
I'm pretty sure there's no patterns going on, that's just a null-coalesced expression-bodied property. Which is juuust on the border of too much complexity for an expression-bodied property for me. Edit: never mind you're talking about that other snippet.

rarbatrol fucked around with this message at 06:39 on Nov 29, 2019

brap
Aug 23, 2004

Grimey Drawer
It’s an empty property pattern which matches any non-null value.

Adbot
ADBOT LOVES YOU

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

Nth Doctor posted:

I attended a 20 minute session on this at Ignite, and still can't get my head around who thought

code:
static int GetMiddleNameLength() {
  if(person.middleName is {} middle) {
    return middle.Length;
  }
  else {
    return 0;
  }
}
was a good syntax choice.

Where did you see that syntax? Is that actually code that was shown in the Ignite session?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply