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
Gul Banana
Nov 28, 2003

yeah, it's not like transactions themselves don't work on azure! they will succeed or fail as a unit. you just might not know *which* of success or failure resulted, due to the nature of distributed systems

Adbot
ADBOT LOVES YOU

Mr Shiny Pants
Nov 12, 2012

Gul Banana posted:

yeah, it's not like transactions themselves don't work on azure! they will succeed or fail as a unit. you just might not know *which* of success or failure resulted, due to the nature of distributed systems

You would think that they would manage this for you, because that is the hard part and they know all the ins and outs of Azure.

Night Shade
Jan 13, 2013

Old School

Mr Shiny Pants posted:

You would think that they would manage this for you, because that is the hard part and they know all the ins and outs of Azure.

code:
CREATE PROCEDURE dbo.ContrivedExample
  @ThingID int
AS
UPDATE dbo.Thing SET ThingValue = ThingValue + 1 WHERE ThingID = @ThingID
Can this be safely automatically retried if we don't know if it succeeded or failed?

Mr Shiny Pants
Nov 12, 2012

Night Shade posted:

code:
CREATE PROCEDURE dbo.ContrivedExample
  @ThingID int
AS
UPDATE dbo.Thing SET ThingValue = ThingValue + 1 WHERE ThingID = @ThingID
Can this be safely automatically retried if we don't know if it succeeded or failed?

I have no clue, can it?

What I am saying is that now everyone has to write these wrappers if you want to run your app on Azure it seems. It looks like a prime example where MS could step up and do this for you with some Azure boilerplate that they write and test.

You know, make things simpler and more robust.

Furism
Feb 21, 2006

Live long and headbang
There's an interview of Scott Hunter (Program Manager Director of .NET) in the latest Eat, Code, Sleep podcast. They mostly talk about .NET Core, explain some of the challenges they had to face and a lot of insider info. It was quite interesting.

http://developer.telerik.com/topics/net/the-net-core-2-wave/

chippy
Aug 16, 2006

OK I DON'T GET IT

Mr Shiny Pants posted:

I have no clue, can it?

It clearly can't. Running it multiple times would have a different end result, and the result would be dependent on how many times it succeeded, because it increments ThingValue. Whereas, for example:


code:
CREATE PROCEDURE dbo.ContrivedExample
  @ThingID int
AS
UPDATE dbo.Thing SET ThingValue = 5 WHERE ThingID = @ThingID
Is idempotent. No matter how many times you ran it and it succeeded, the resulting state of the system would be the same.

edit: Oh hang on, are we asking if the ContrivedExample sproc is idempotent, or the CREATE PROCEDURE statement?

chippy fucked around with this message at 14:15 on Jan 18, 2017

EssOEss
Oct 23, 2006
128-bit approved

Mr Shiny Pants posted:

What I am saying is that now everyone has to write these wrappers if you want to run your app on Azure it seems. It looks like a prime example where MS could step up and do this for you with some Azure boilerplate that they write and test.

It is true that for trivial applications, you could often get away without this if all you were doing was communicating with a database on localhost - not much that can break the connection in that scenario. While it would certainly ease uptake of Azure SQL for trivial solutions, I get the feeling they do not really target the trivial solutions.

For any software of serious size, where you have a real live network between your app servers and your database server(s) and where you might perhaps be hitting some limits of the servers or infrastructure every now and then, retry policies are required no matter what. Azure just makes a "seriously business" style environment the default that everyone encounters. It does scare away people who are used to simple setups with tiny apps but it makes sense from Microsoft's perspective - after all, what would be the point in developing separate infrastructure just for the nonscalable simplistic setups.

In any case, retry policies are a matter of business logic. This is not a technical obstacle that Microsoft could solve with some boilerplate code, so to speak. It requires active decision making by the people designing the software that is using the database. The right answers will be different for each case and there is not much Microsoft could do here to fix it. Granted, they could certainly document it better and provide some examples that actually showcase this, so there is some justified griping about it.

Night Shade
Jan 13, 2013

Old School

chippy posted:

edit: Oh hang on, are we asking if the ContrivedExample sproc is idempotent, or the CREATE PROCEDURE statement?

The EXEC side, not the CREATE side. CREATE isn't I think technically idempotent because it will fail if it is executed a second time but it is safe to automatically retry.

I was (badly) alluding to the fact that it's trivial for devs to create code that is guaranteed unsafe to be automatically retried, and if Microsoft puts in some sort of infrastructure for doing so those same devs will blindly turn it on and then blame Microsoft when ThingValue winds up at 2734 instead of 5.

Night Shade fucked around with this message at 22:48 on Jan 18, 2017

Mr Shiny Pants
Nov 12, 2012
not important.

Mr Shiny Pants fucked around with this message at 23:32 on Jan 18, 2017

ljw1004
Jan 18, 2005

rum

EssOEss posted:

In any case, retry policies are a matter of business logic. This is not a technical obstacle that Microsoft could solve with some boilerplate code, so to speak. It requires active decision making by the people designing the software that is using the database.

Personally I reckon that this is the most important piece of software value that you contribute as a software architect...

Most everything else in your code is boring data structures and boring ways to wire them up in the obvious ways, or tedious configurations of one sort or another. The only places where you get to actually craft novel things with your skillset is in distributed correctness -- it's different each time, always subtle, always elegant. I guess if you work on low-level stuff at places like Google then you also get to craft elegant datastructures+algorithms+concurrency too.

I wonder where other folks here get their "joy of coding" from?

Potassium Problems
Sep 28, 2001

ljw1004 posted:

I wonder where other folks here get their "joy of coding" from?

For me, a bottle of Maker's Mark

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings
I've got a binding breaking in this UWP app and I can't figure out exactly what the hell is failing.

The structure I have to work with is such:

UserControl Foo exposes a TextColor DP.
Foo primarily contains a ListView.
That ListView has an ItemTemplate.
That ItemTemplate is simply a Bar, with Content bound to itself.
Bar is a resolver class, which exposes a number of DataTemplate properties for all the various subtypes of the ListView's ItemsSource, and upon ContentChanged mutates its ContentTemplate into the value of the associated property.
All of these SubTemplates expose a TextColor DP that they use internally.

The XAML ends up looking like:
code:
<Foo x:Name="Foo">
	<ListView>
		<ListView.ItemTemplate>
			<DataTemplate>
				<Bar Content={Binding}>
					<Bar.SubTemplate>
						<DataTemplate>
							<SubTemplateControl TextColor={Binding TextColor, ElementName=Foo}>
But that final layer of binding is just DOA. The text element inside SubTemplateControl just ends up using whatever default value is declared on the DP. What's baffling me is that the binding *does* try to resolve, as if I add a change callback, I can verify both that it's firing, and that the expected bound values are coming through just fine. No binding errors are getting logged or thrown, it's just oddly...not updating.

Cuntpunch fucked around with this message at 16:42 on Jan 19, 2017

EssOEss
Oct 23, 2006
128-bit approved
I have an ASP.NET web API that calls other web services, making around 100 requests per minute in total. I found that every few hundred requests, PostAsync() takes an additional 3 seconds to return (so instead of 10ms it takes 3010ms). Sometimes it is a multiple of 3 seconds (6, 9 or more seconds) but the delay is always very precise, with no deviation when it occurs.

At first I thought some network funny business but no - this effect disappears if I use a shared HttpClient instead of creating a new one for each call.

The fact that such unintuitive behavior can exist in an HTTP stack is pretty mind-boggling to me. I just wanted to share.

Red Mike
Jul 11, 2011
It's not made anywhere near clear enough that HttpClient is meant to be shared across as many of your requests as you can because creating and disposing it constantly is expensive.

It gets better, because it queues internally when too many requests are being made. It gets even better, because the timeout on the request includes the time spent in the queue. It gets even better because by default a timeout will not only time out the currently running requests, but also all the queued ones (unless you provide a CancellationToken yourself). And let's not mention that the timeout shows up as a TaskCanceledException.

Kekekela
Oct 28, 2004

ljw1004 posted:


I wonder where other folks here get their "joy of coding" from?

Client side stuff for the most part these days.

e: Also, I think that's a brilliant question and am curious as to how fellow goons might answer

Mr Shiny Pants
Nov 12, 2012

Red Mike posted:

It's not made anywhere near clear enough that HttpClient is meant to be shared across as many of your requests as you can because creating and disposing it constantly is expensive.

It gets better, because it queues internally when too many requests are being made. It gets even better, because the timeout on the request includes the time spent in the queue. It gets even better because by default a timeout will not only time out the currently running requests, but also all the queued ones (unless you provide a CancellationToken yourself). And let's not mention that the timeout shows up as a TaskCanceledException.

So we are back to using plain old webrequests? There was someone in this thread who also had a weird problem with HttpClient killing all the outstanding requests on an Exception.

Warbird
May 23, 2012

America's Favorite Dumbass

lovely developer here.

I've been poking around with program persistence for the sake of making more complicated applications, and I'm pretty terrible at it. For the sake of scope I've been trying to make an extremely basic Winform log on screen. No security or anything like that; I just want it to check if the username/password combo in the text fields exist within a database and prompt if they don't.

What I don't quite get is actually linking the DB and the program. I've gone through a few guides, but most have you making the SQL DB in SQL Server Manager or the like and passing connection and query strings to it to do your business. MSDN's guide has you making the database within VS and the project it corresponds to, but it kind of falls off a cliff when it comes to getting the program to pull and push to the DB. I can get a datagridview to do this no problem via drag and drop, but that's clearly not desirable in most situations. I've got a DB within the server explorer and a data source associated with it and the fields I want, but I'm pretty lost at this point. How do I leverage having the DB being made with VS? My knowledge is wide and shallow development, so please assume I'm an idiot.

Side question, why is VS2015 Community such a memory hog? I'm sitting at 2 gigs of memory usage right now on an idle single project solution with no add ons.

Mr Shiny Pants
Nov 12, 2012

Warbird posted:

lovely developer here. <- Don't be too hard on yourself :)

Take a look at Entity Framework, it is the new blessed way of doing DBs in MS land.

https://msdn.microsoft.com/en-us/library/aa937723(v=vs.113).aspx

Otherwise take a look at SqlCommand:

http://csharp-station.com/Tutorial/AdoDotNet/Lesson03

do make Parameterized queries.

Weird, mine is at 300mb with Xamarin loaded.

Red Mike
Jul 11, 2011

Mr Shiny Pants posted:

So we are back to using plain old webrequests? There was someone in this thread who also had a weird problem with HttpClient killing all the outstanding requests on an Exception.

Fairly sure that was me.

Using HttpClient is fine, but you have to:

  • Always use SendAsync, and always pass in a new CancellationToken for every request. This prevents one cancellation from cancelling all pending requests.
  • Always use one shared instance instead of creating one for every request. This prevents slowdown due to cleanup/startup of HttpClient.
  • Preferably, use one shared instance for every type of request. There's some amount of caching of paths, dns lookups and such going on, keeping independent instances for entirely different things is a good idea either way.
  • Be aware that the time counted for timeout includes everything from as soon as you call that send method. If you aren't keeping this in mind, requests queueing will bite you in the arse.

Except for that, the only outstanding issue I still have is how DNS name resolution actually works internally, because I keep running into issues like: I use HttpClient to contact something behind a DNS load balancer (Route 53 weighting), it keeps using the same IP it resolved to initially on all requests through the same HttpClient instance. Or more recently, the datacentre's DNS server screws up for a second while I'm requesting something and sends me a completely wrong IP address for the name I requested, that wrong IP address is cached until the process is restarted, causing constant errors until someone goes online to restart it.

e: ^^^ I cannot recommend getting someone starting out to use EntityFramework, especially if they're new to the whole database thing in general. Use something like Dapper.NET, build queries yourself, run everything yourself. Only then should you toy around with EntityFramework, so you can get nice and mad about all the insane things it does when you accidentally tell it to do insane things.

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Red Mike posted:

e: ^^^ I cannot recommend getting someone starting out to use EntityFramework, especially if they're new to the whole database thing in general. Use something like Dapper.NET, build queries yourself, run everything yourself. Only then should you toy around with EntityFramework, so you can get nice and mad about all the insane things it does when you accidentally tell it to do insane things.

Ditto. EF makes things easy if you know how to use it (and if you don't), but it's also very easy to do really stupid things. For learning how to use a database you're better off actually using a database.

Mr Shiny Pants
Nov 12, 2012

Bognar posted:

Ditto. EF makes things easy if you know how to use it (and if you don't), but it's also very easy to do really stupid things. For learning how to use a database you're better off actually using a database.

Hmm all the MS docs seems to use EF for anything DB related, even beginner stuff. I agree that is quite a lot to learn, so I'll join you in saying that EF might be overkill right now. :)_

Ochowie
Nov 9, 2007

Red Mike posted:

e: ^^^ I cannot recommend getting someone starting out to use EntityFramework, especially if they're new to the whole database thing in general. Use something like Dapper.NET, build queries yourself, run everything yourself. Only then should you toy around with EntityFramework, so you can get nice and mad about all the insane things it does when you accidentally tell it to do insane things.

Yeah, most EF tutorials seem to use LINQ as the query interface to EF and I think that obscures a lot and makes it really easy to write code that produces horrible queries on the database side. I think if someone is just starting out with DB access they should use SqlCommand with SQL written by hand.

Red Mike
Jul 11, 2011
Or just use something like Dapper.NET and skip the constant trouble with the correct way of opening connections, reading into the appropriate variables, turning stuff into lists, etc. You're still writing your own SQL, just skipping the boilerplate.

Warbird
May 23, 2012

America's Favorite Dumbass

Majoring in MIS in school has many benefits, but playing ball as a SD ain't one of them. Most of this is exploratory stuff during slow periods at work, so I'll have to make sure there won't be any issues with me poking around with those toolsets. Wouldn't want to lose local admin privileges.

For reference, this was where I started iirc. Here's about where things went sideways with connection strings and whatnot. This is the EntityFramework mentioned before, correct?

I was able to get something somewhat working via looking at this example project, but it appears he made that while sleep deprived and somewhat drunk if I remember some of his comments correctly. It has more than a few issues. Still, it's a step above me watching some Russian youtube videos with no subtitles in order to figure out how the hell to do something like I usually end up doing at some point in a project.

Warbird fucked around with this message at 21:19 on Jan 20, 2017

Bognar
Aug 4, 2011

I am the queen of France
Hot Rope Guy

Mr Shiny Pants posted:

Hmm all the MS docs seems to use EF for anything DB related, even beginner stuff. I agree that is quite a lot to learn, so I'll join you in saying that EF might be overkill right now. :)_

The MS docs focus on EF because they want to make everything seem easy to use so that developers will adopt their technology. Understanding what's going on under the covers is hard, so they don't dwell on that.

Paul MaudDib
May 3, 2006

TEAM NVIDIA:
FORUM POLICE
Today I came across this list of libraries that support/don't support ASP.Net Core, which seems useful. You can probably take it as a proxy for poo poo that is mature/significant enough to care about.

https://github.com/jpsingleton/ANCLAFS

Furism
Feb 21, 2006

Live long and headbang

Red Mike posted:

  • Always use one shared instance instead of creating one for every request. This prevents slowdown due to cleanup/startup of HttpClient.
  • Preferably, use one shared instance for every type of request. There's some amount of caching of paths, dns lookups and such going on, keeping independent instances for entirely different things is a good idea either way.

How do I do that in a WebAPI project (the ASP.NET Core version, I guess that's technically ASP.NET5)? Won't the instance be destroyed as soon as the Action is done? Would it work is Dependency Injection?

Red Mike
Jul 11, 2011

Furism posted:

How do I do that in a WebAPI project (the ASP.NET Core version, I guess that's technically ASP.NET5)? Won't the instance be destroyed as soon as the Action is done? Would it work is Dependency Injection?

The same way you would call services from your controllers. Either have an instance be created with your controller (which means it's not technically one shared instance, but it's close enough) or with something like Simple Injector, and you can define a lifetime there.

Chamook
Nov 17, 2006

wheeeeeeeeeeeeee
If you create a class that implements IHttpControllerActivator you can use that instead of the default for creating your controllers on each request, you can then create a HttpClient on app start and pass that into the constructor of your ControllerActivator so you use a single shared HttpClient for the lifetime of your application.

Red Mike
Jul 11, 2011

Chamook posted:

If you create a class that implements IHttpControllerActivator you can use that instead of the default for creating your controllers on each request, you can then create a HttpClient on app start and pass that into the constructor of your ControllerActivator so you use a single shared HttpClient for the lifetime of your application.

With the proviso that "app start" might mean (depending on hosting method) something other than "the application start". What it'll actually mean is "when the app pool gets initialised, which will be on the first received request without an active app pool; also app pool can get torn down if no requests are received for a relatively short amount of time".

e: oh also if you do long-running pre-caching of data in that setup step, don't. Because then this data pre-fetch will take ages and delay a request apparently randomly if the user is unlucky to have done the first request since the app pool was torn down.

NihilCredo
Jun 6, 2011

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

https://twitter.com/Nick_Craver/status/821590537262268416

ljw1004
Jan 18, 2005

rum

Furism posted:

How do I do that in a WebAPI project (the ASP.NET Core version, I guess that's technically ASP.NET5)? Won't the instance be destroyed as soon as the Action is done? Would it work is Dependency Injection?

Doesn't just a normal static variable maintain its life across multiple actions?

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer
Unless I'm missing something here, if you're using WebAPI in ASP.Net Core (technically the WebAPI and MVC pipelines have been merged together in Core, so WebAPI isn't really its own thing anymore) you should be able to use the Singleton lifetime to inject the same HttpClient instance for every request. Put services.AddSingleton<HttpClient>(CreateMyHttpClient()); in ConfigureServices in your Startup class, and include HttpClient as a parameter to the constructors of your controllers. That's a little more testable and replaceable than using a shared static instance.

ljw1004
Jan 18, 2005

rum

LOOK I AM A TURTLE posted:

Unless I'm missing something here, if you're using WebAPI in ASP.Net Core (technically the WebAPI and MVC pipelines have been merged together in Core, so WebAPI isn't really its own thing anymore) you should be able to use the Singleton lifetime to inject the same HttpClient instance for every request. Put services.AddSingleton<HttpClient>(CreateMyHttpClient()); in ConfigureServices in your Startup class, and include HttpClient as a parameter to the constructors of your controllers. That's a little more testable and replaceable than using a shared static instance.

I'm not very good at testing. Could you spell out in a bit more detail how "more testable and replaceable" would apply to HttpClient?


My first guess is that you might want to mock HttpClient. That way you could run a method in isolation, pass in your mocked version, and verify that it called a particular method on HttpClient with the right URL. You probably wouldn't provide mock bodies in your mocked HttpClient I'm guessing, because it'd be so tedious and unlikely to catch regressions.

I reckon the defense against bugs I'd want in my code would be (1) against the webserver giving a different format in its answer, (2) against timing differences in the webserver response, (3) against a wide variety of different error codes returned by the server, (4) against partial success. Would you go the whole hog and provide a "testing version of HttpClient" that does this kind of stuff?

For replaceability, is there any cause you'd have to replace HttpClient (other than testing)? I guess that I'd only ever replace a higher-level abstraction of it, i.e. a class I write which has only a tiny number of methods. But HttpClient feels basic enough to me, like "int" and "string", that I don't think I'd even try.


I am really lousy at testing :)

Night Shade
Jan 13, 2013

Old School

ljw1004 posted:

I'm not very good at testing. Could you spell out in a bit more detail how "more testable and replaceable" would apply to HttpClient?

You can then inject an HttpClient using a custom HttpMessageHandler that returns canned responses/failures/timeouts instead of actually making web requests.

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
Real quick informal poll:

Of the devs who work on a VM, what are your experiences with it? What kind of resources do you have available within the VM?

We're having a lot of trouble getting our VMs up to speed here and I'm hoping for some advice. We develop mostly web apps, and starting up the MVC projects in debug seems to take forever on our VMs. Even just opening the projects seems to take far too long. Is Visual Studio just a slow IDE, or is it likely that it is straining for resources?

It's easy enough to find bare minimum system requirements for this kind of thing, but getting actual real world "This is what you would actually WANT to have" figures is tricky.

putin is a cunt fucked around with this message at 23:02 on Jan 23, 2017

No Safe Word
Feb 26, 2005

The Wizard of Poz posted:

Real quick informal poll:

Of the devs who work on a VM, what are your experiences with it? What kind of resources do you have available within the VM?

We're having a lot of trouble getting our VMs up to speed here and I'm hoping for some advice. We develop mostly web apps, and starting up the MVC projects in debug seems to take forever on our VMs. Even just opening the projects seems to take far too long. Is Visual Studio just a slow IDE, or is it likely that it is straining for resources?

It's easy enough to find bare minimum system requirements for this kind of thing, but getting actual real world "This is what you would actually WANT to have" figures is tricky.
Until a role shift that doesn't require nearly as much time in Visual Studio I was spending 100% of my time in a Virtualbox VM with the following specs:
- 10GB of virtual RAM (the laptop has 16GB)
- allowed to use all 4 cores, with an execution cap of 100%
- running Windows 10, VS 2015
- network was actually plumbed through 3 different interfaces: 1 pure NAT, 1 bridged directly to the wired ethernet, 1 bridged directly to wireless (I mostly kept the latter two disabled but if I needed to I would disable/enable from within Windows and it worked like a charm)
- 150GB VDI disk

This is on a relatively recent laptop (~2 years old now):
- i7 5600U 2.6GHz, quad core
- 500 GB SSD

The base OS is running Debian Jessie.

The performance was pretty good. Not amazing, but pretty good. I was able to drive all three screens via three separate VBox screens which was nice. It flipped out when I docked/undocked fairly regularly though. Rebooting the VM fixed it though.

LOOK I AM A TURTLE
May 22, 2003

"I'm actually a tortoise."
Grimey Drawer

ljw1004 posted:

I'm not very good at testing. Could you spell out in a bit more detail how "more testable and replaceable" would apply to HttpClient?

I am really lousy at testing :)

I don't think I've ever used HttpClient directly myself, so I can't speak to the specifics of how you would want to test it or whether it makes sense to replace it with a different implementation. I guess I could extol the virtues of using DI here, but it would be in very general terms.

Out of your examples, "(3) against a wide variety of different error codes returned by the server" at least sounds like a good case for using a mock. You'd mock up a fake HttpClient and set up SendAsync (or whatever) to return different HTTP codes, and verify that your code does the right thing in each case.

As for it being "replaceable", what I'm getting at there is that you're making your dependency more explicit. The principle behind Inversion of Control is that if a class/module/function/etc depends on something, you can "break" the dependency by allowing the caller to override it. The theory is that if class A calls a method on class B, you can make it easier to change functionality in the future by letting the caller of A override B -- especially if A and B live in different codebases. I think of this as the OOP version of higher order functions. Whether it's relevant in the case of HttpClient I can't say.

Technically you can do the same stuff with something like a static property, but using a DI framework can be a little more elegant. In ASP.NET Core I would definitely recommend using DI whenever possible since the whole pipeline is designed with DI in mind.

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

Furism posted:

How good is the "C# in Depth" book (http://csharpindepth.com) ? I'm looking for a good reference and best practices book.

Is there a book like this that someone can recommend that includes C# 6 stuff as well?

Adbot
ADBOT LOVES YOU

zerofunk
Apr 24, 2004
I thought I had read something about a new edition being in the works, but I can't seem to find anything now. With that said, I feel like there wasn't that much added in C# 6 that'd provide a lot of content to the book. I'm probably forgetting or shortchanging something though. Just seemed like a lot of the additions in C# 6 were fairly small syntax type things. Nothing on the scale of generics, async, etc that fills a lot of C# In Depth.

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