 I think there's still some confusion around .NET standard, particularly around why it was invented and how it affects the apps you're currently building. On this episode of Visual Studio Toolbox, Kathleen Dollar is going to do her best to clear up that confusion. Hi, welcome to Visual Studio Toolbox. I'm your host, Robert Green, and joining me today is Kathleen Dollar. Hey, Kathleen. Hi, how are you doing? Great. We've talked quite a bit about .NET standard. We've been Microsoft. Emo has done several videos on Channel 9. It was featured at Connect. You talk about it at conferences, and yet I think there's still some confusion about it. And yet. And yet. So what we're going to do in today's show is clear up some of the confusion, not so much about how it works, because I think that's been covered very well. I agree. But more about the why it was invented, why and when people should care. Just for example, if I'm maintaining existing WinForms or WPF apps, do I need to care about this? Well, to start with, if all of your code is in your WinForms app and your WPF app, you can't use .NET standard. It's really not in the picture. But on your WinForms app or your WPF app, you might have some of your code in the WinForm and WPF application itself in that entry point, and then you might also have some class libraries that you're using with that. That I've already written. You've already written or now I inspire you to split them out and put them into something. But you've got now this class library. You can take the class library and have it target .NET standard. And that's what you can do. And we can talk more about why you want to do that. So do you want to go there now or do you want to talk about all the other ways you might wind up caring about .NET standard? There's another example. So I do a bunch of Xamarin and I do File New Project. And there's always been two buttons, Shared Project and the other button, which used to say Portable Class Library. Then magically it said .NET standard library. I always choose that one because it's not the Shared Project. And then I do the exact same thing. Is I write the exact same code, I put the code and the XAML in the exact same place. And when I build the application, I understand it's using .NET standard instead of a Portable Class Library, but I haven't done anything different. So why? In that case, that's great. Behind the scenes you are using .NET standard instead of a PCL. And there are some key differences between the two. So let's start off with why that happened. What was wrong with Portable Class Libraries? Last time anybody checked, when we did an episode on it a couple of years ago, they were awesome. So all of a sudden they're out, unceremoniously dumb. Yeah, they've been dumb. What did they do? They were actually pretty cool. So they were great. It's just that .NET standard is that much greater and that much cooler. So let's talk about the difference. So Portable Class Libraries walked into a world where there were a lot of frameworks. And across all these different frameworks, there were different rules that API was just a little bit different. Okay, so what a PCL does is says, those things you have in common, you can use. If it's not in common between these two things, you can't use it. And if you add a new target, you're going to change what you can do. So you could have like .NET, you could use PCL and it could be like Xamarin and something else and you're out there in the field and everybody's happy. And all of a sudden somebody says, let's target Silverlight. And then as you add that other requirement in, you lose a bunch of APIs and you can actually break yourself in the field. So because PCL was always an afterthought, they don't fit into today's world as well as we want them to. So everybody took a step back and they said, well, instead, let's create the standard ahead of time. Now, HTML5 is a standard. Okay, this is what a standard is. It's basically a document somewhere. So there's the .NET standard, people got together and said, this is the things we can agree on. And there was a lot of work to actually get the right set of features in that. Now, if any platform, any framework is gonna say, I support .NET standard, they have to follow those rules. So instead of being an intersection of what was already written, it's a standard that then gets pushed out and people have to adopt. Now, that doesn't mean that .NET, say full framework or Xamarin has to make internal changes because it doesn't matter how they implement this. It can be any way in the world. A lot of the Xamarin stuff actually pretty well aligned and so it can just call straight in, it's just fine. For the rest of the stuff, there needs to be, for like .NET framework, there needs to be a redirect. So it says, oh, you said you wanted to call this but I know what you really mean is this API that's just a little bit different and we'll just redirect you over there. We're, where is, okay. I'm surprised, Robert. You lost me on that one. I write some code, targeting what I think is the .NET framework but I'm not, is that what you just said? If you're targeting .NET standard, you're actually targeting .NET standard. It's what we call a reference DLL and let me show you real quick what that looks like. So if I come over here and I go to the .NET standard, this is actually GitHub, .NET standard, pick one. Which one do you wanna pick? It's just not data. We'll do data. Okay, so I'm just gonna open that. Just open it. No right click, just open it. Come on. Okay, so when this opens, you're gonna see the actual .NET standard. So it's a standard. It's a document. It's a document written in code. You with me? All right. So this is what it actually looks like and it has enums because of course we need those to define the API surface level but it also has a class. Now there's something kind of unusual about that class. It doesn't do anything. Right. It's either empty or it throws. Okay, that's it. So a reference library is a library that's empty. So this works just fine. You can target this and Visual Studio or your build system or anything that needs to understand your libraries can look at this and go, hey, I get it because they don't care that nothing actually happens. And then when you go to run on your full framework machine then this is called Net Standard DLL. That's what this builds. So that's on your box where you're doing your build and then you go to production and you go over and whether it's a Linux box or a Mac box or a Windows box, goes there and it says, well there's a Net Standard DLL associated with the framework I'm running now. Use that Net Standard DLL which doesn't have empty places instead of the one that you compiled against. So inside of those brackets it may say, oh, don't do this, do that. So the brackets here may call a different API or an API that's just in a different spot and all of that gets worked out however that framework wants to do it. The only requirement is that there be a Net Standard DLL specific to that framework so that when you write your app and you target Net Standard DLL and you target this empty reference library it can get thrown out and a real one that actually works can be put in place. So the purpose of this document here is to set the rules on what you can call just like a portable class library said, you are allowed to call this subset and if you try to write something that isn't supported you'll get a compiler error because it doesn't exist. This is now a better, more flexible way of accomplishing that, right? That compile time, if I call something that isn't in Net Standard and I've said I'm targeting Net Standard then I'll be alerted that I'm calling code that essentially doesn't exist and can't be called. That's correct, yes. So all of that works very similarly and the difference is that with PCL there was no way to change the API surface if it was just a little bit different it did the same thing but it was just a tiny bit different. There wasn't a way to really resolve that in a PCL world. Now we resolve it because on the machine that's actually running where code's actually executing, it's not empty. There's something in there and whatever that thing is, it might just do the job if it's simple. It might ask something else to do it. It might do, there's even some binding redirects and things that can be involved and so all of that stuff happens behind the scenes. That's part of what Emote talks about is folks wanna see that in his videos because he wrote this stuff, he really understands that deep level. What I want us to talk about is why people care and what's the one we step back what's the impact of this on individual developers going forward. So just like with portable class libraries the main impact is one of the main impacts or is it the main impact? Comes if you're writing code it's going to run on multiple platforms. It is the main impact. That the main impact. It's not the only impact but it is the main impact. And the other impact comes from the fact that this is also a statement of what Microsoft has determined is the commonality across platforms. So another way we can say that is this is the definition of the future for the non, I'm calling it entry level but the non UI pieces. So for everything else including some things around console apps for all of these things this is what's defined as where we're going in the future. And so even if you're not actually going to run on a different platform if you go ahead and target .NET standard then you're able to say hey I know I'm within the bounds of what the future is likely to look like. And if it's something that's outside of that then I can look for some help for how I get that job done. Because .NET standard 2.0 and there's been a couple of iterations of it was not randomly created. A lot of code was evaluated in order to see what do people actually do. And it covers the vast majority of what people actually do. So if you're writing an application and you say oh I want to do this thing let me see if it's in .NET standard let me see if I can do a little different for it to work in .NET standard. And this also supports some of the deprecated and out of date ways of doing things so when we look at areas like XML and areas like that we've had a few iterations of how to approach those. And this lets you say hey this is the one that I expect to use going forward. So where there's something missing there's often a replacement that is a better way going forward. Okay so I'm working on an existing WPF app where I'm creating a brand new WPF app and I want to build a class library. I can just build the class library the way I always do. I can not worry about .NET standard. I have access to the full framework from within WPF and I can go and do that. Absolutely. And if this DLL is only ever going to be called from that WPF app then I can just happily do that and not need to think about .NET standard. And if I don't think about it I haven't lost anything. And the only thing I'm going to challenge on that is I'm going to say that it's very hard for you to say never ever anybody else will ever want my class library. It's easy to say Robert but let's look at the world around us and how much change we've seen. And your class library is important and your class library you want it to last for five or 10 or 15 years. So if you want to write it with that kind of thinking and you say well I'd like to still be on WPF in 10 or 15 years and have that still be cool but I don't really know what's going to happen there. I do know that the core way that we write applications has been pretty static now for a really, really long time. And Microsoft has found a way to move forward across a lot of technology change using pretty much the same code. And the APIs is now, this is an API level conversation and this is a way to say the APIs are going to have a pretty long life. They're not that they'll never change it's just it's going to change at a very slow level. So you do the best job you can to say that my WPF app that work in the background, this business logic, that extra work that's going on. I'm going to future proof that by having it understand.net standard. Now, you don't actually have to target.net standard. You can do this a slightly different way if you'd like. You want me to show you how you can. Yeah, let's talk about that in a second. So I decide, okay, future proofing is probably good, right? So I'm going to target.net standard. I'll create the class library, targeting.net standard. So finally project.net standard library, I assume, right? Exactly. And I target the latest version of the.net standard. Okay, it's a good choice. Depending on what version of Visual Studio I'm in, right? Because each version targeted a different version of the.net framework. But the.net, how do I know that.net standard 2 supports all of the things that I would have done in my app if I was directly going against the framework? Am I going to, are there things not available to me? And is there a way to know that ahead of time? There's more than one way to know that ahead of time. So I'm going to open a new browser window here and I'm going to type APIs, APIs of.net. I'm going to go there and what is your favorite, what is your favorite class or method in side of.net? So it's got to be something in system.data. You like system.data? I do. I'm going to go with that. Let's get a little more specific. Oh, let's go to link. Link, okay. And let's go to, I don't know, pick one of those. Okay, we'll just pick anything. We'll just pick a, I think I'll pick a. Refresh mode. Refresh mode. Table, table. There we go. Table. No idea what we're going to get here. So let's just pick that. Come on, we can do this. Okay, so what we've done is we've gone to a evaluation of the API itself, the API surface layer itself. So we can see what this class is. We can find out some things about it. We can find out how many people use it, okay? So 0.3% of users in one of the ways that this gets evaluated. So this information was used in order to build the surface area of the .NET standard. And so they also make it available, because Microsoft has a, at least in the .NET core, we share our temperature. 0.3% of apps doesn't seem very high. That does not very high. This does not get used very often. Well, this is system.data.link, and that's not a real common thing. Okay. We can see where it is. It's in .NET full framework, 3.5 and 4, coming forward all the way. It's in mono, and it's in Windows Phone, Silverlight. Okay. Okay. Now, I'm going to pick one in my turn. So I'm going to look for system.string. And I bet yours is more, but this is, you know, this is rigged. This is a rigged podcast here that you've done a demo before. Okay. So we can find out some things about the system.string class, and we can look at its usage. And I just wonder about the 15% or so percent that don't use a string. But most things use a string. Most applications use a string, not surprisingly. Now, let's find out some more things about it. It's in .NET Core. Remember, yours was not in .NET Core. So now I can see. So when I know the actual thing I'm looking for, I can find out where it's used. Okay. This is one of the things you might want to do. More commonly, I think what you're going to want to do is look at your code to see, hey, will this pass the muster, well, can this be a .NET standard app? Could I change this to be a .NET standard class library? What am I using and how would that go? And there's something called the .NET Portability Analyzer, which you can get off of, click this so you can see it. It's in the gallery, it's in Visual Studio Gallery, or Marketplace, I guess we call it Marketplace now. And I have that open. I have just a silly little sample. This is just one of the link samples and I just grabbed one randomly so we could see what's going to happen when we run this. So because I have installed that tool, it's a Visix, it's a normal installation, because it's installed, when I go to the solution explorer and I right click, I have an option to analyze. Okay. I also have an option to set settings. So let's do that first because it helps show what's going to happen here. So this is kind of an ugly dialogue, but you can see what it does. You get to pick what it analyzes. Look at all your choices. Okay. So if you want to know if something will run on Windows, Phone, Silverlight 7, you can find out. Okay. Okay. So let's come up and look at the ones we care about, which is .NET Core. And I've got .NET Core 2.0 clicked. I think I'll also do .NET Standard, 1.4, 1.5, 1.6, and 2. Those seems like some pretty good ones. Okay. Unless there's something you see there, you just really want me to click too. That's fine. Okay. So because I've got that, I'm going to cancel out of this dialogue because I made no changes. I'm going to right click, and then I'm going to say, go ahead and analyze. And if, assuming I have an internet connection, because this does rely on internet connection, and if it doesn't, it found the internet, it was just fine, if it doesn't have an internet connection, then you're going to have to find that before this works, because it's real time. Okay. It looks it up right away. So now what I'm going to do is open the report. And it's going to open because I actually had an option in that dialogue that it would open in Excel. Right. So that's how it knows to open this. And it's a little small for being on screen here, so let me just make it a tiny bit bigger. And what we know now is that the .NET Core, it's 100% compatible with that. .NET Framework, and I'll click this. So up at the bar at the top, you'll see that this is .NET Framework. Right there, click that. This is the .NET Framework. .NET Standard 1.4, 1.5, and 1.6. This is .NET Standard 1.6, and .NET Standard 2.0. Okay. So you can see that we're 100% compliant with two and not the others because two contains more than the others. So there's something. Right. So something's going on here. And you're going, okay, so that's not very helpful yet. You're going, I can't fix my code. It's interesting, but I can't fix my code. The exact question you asked, which is how do I know what I need to target? I've got code and I want to know what I could target. I do know that now. I know that I can target .NET Standard 2.0 right now out of the box. With that code as it exists. No changes. Okay. But the question I'm probably going to want to ask if I'm interested in targeting something lower is, yeah, what did I do? Right. Where did I mess up? Where did I cause a problem? And so you find that on the details tab. So when I switch to the details tab, and again, I'm going to click this up just a little bit, not that far. See if I can't get it. We'll see if I can do it. Let me just use this mouse over here, see if I can get a little bit better at this. Okay, that's probably good. Okay. So now what we can see is that the description attribute and the category attribute, each of which was used twice in the sample, is what's the problem. And I can then go over here and find out where it came in. And so in .NET Core and .NET Core, it came in in 2.0. Because in the .NET Core column, it says supported in 2.0 and above. In the .NET full framework, it was supported in 1.1 and above. Okay. I haven't seen anything that's 1.0, it may 1.1 maybe the baseline. And then for .NET standard, it says it's supported 2.0 and above, which is exactly what the previous page told us, is that we need to go to 2.0. And what is it that is supported join operators? No, join operators is the name of my assembly. Yeah, oh, okay. That's the name of my assembly, let's go back. That we're talking about here. So it does not tell me the line of code, it simply tells me what I'm doing. So now I can go and look for where I'm using the description attribute and the category attribute. And that's what I know I have to pull out of my app. So I could just use a search or something to find those. Okay. Okay. So now I know what it is I'm using. I love doing feature requests there. It'd be really cool if I could set that and then compile and it would show me. The actual lines of code. Red, yellow, green squigglies. Exactly where it is. And the code, an error list and the task list. Yeah. That would be great. If you want that, one way to do that is to try to target what it is that you're interested in. And then if you target it and it doesn't work out, then you're going to be able to go straight to that code. And at this point I might do that for this application. It doesn't seem like it's going to be a huge wall of problems. But now I know if I bring my application up in here and you might want to even run a unique to find out how many different things you're using and just how big the job's going to be to take your application into the .NET standard or anything else. You saw that list. You can check out any, I mean, there's a bazillion different frameworks that you can select there to see how your code lines up with that. So you could take code you've currently, you've previously written, right? That's correct. Take, you know, go and find representative samples of code you've already written, put it into a .NET standard library or run the analyzer on it. Just run, you don't have to move anything. To see, yeah, you don't have to move it yet. And then when you discover that there are hopefully fewer, but maybe more incompatibilities than you thought, then you could actually build that as a .NET standard library, try to compile it and go see what code doesn't run. If it's too much, then you have the choice of either not doing it or figuring out how to accomplish the same thing with code that is supported. Correct. And I would suggest that just about everyone who already has a class library should think about doing this because it gives them information for that moment that their boss or somebody says, oh, I heard about this .NET core thing. And if you know that, man, you've got problems, and you already know that, then you know, just wave off the conversation. And if you know, hey, we don't think we're that far, then you can say, we might be able to do that, but the problem is going to be what we're going to do on our UI side because we don't have cross-platform UI. We have that is very specific to what you're doing. So if you're running Xamarin, then that's great and the Xamarin can call into a class library and then UWP or WinForms or WebForms can call into the same library. Which could certainly be a scenario. You have a desktop client application, whether it's UWP or WPF or WinForms, or you've got a web app with middle tier code. And now someone says, we want to put a mobile front end on that. Let's reuse the logic. Exactly. That could easily happen and hopefully does easily happen. That is absolutely what DotNet Standard is designed to do. This makes it a lot easier for you to target that scenario. DotNet Standard is the setup to target the scenario. And there's these tools that are set up to make it easy for you to, first of all, just assess. It's just, I have no idea. I have no idea how I sit. Do I have to convert and then see what goes wrong and fight through that? Or is there a way that you can just, in just a couple of minutes, give me a report, which is what the portability analyzers. For most people, it's going to take longer to install than run across there. So it's a pretty fast tool. So there's one more thing that's also available in the analyzers, which I'll show you real quick, which is if I, you can close that. There's something else I also have installed, which is just an analyzer. And analyzers are installed per project, where the tool I just showed you, because it's actually a Visual Studio tool. First of all, it doesn't run in code, sorry. And second of all, it does, it's not per project. It's always available after you install it. But here I have an analyzer. Let me just get that open here. If I go under references and I go under analyzers, I have one installed, which is called the compatibility analyzer. Move that over so we can see it. It's a compatibility analyzer. I get that off a new get, because that's where we get analyzers. And so now if I use a great variable name, I'll use my favorite variable name. And I'm going to say new web client. That happens to be a deprecated API. So I can find out that it's- Deprecated in what? It's deprecated in .NET full framework. Okay. So .NET standard doesn't have deprecated things. They're not there. All the deprecated things got left behind. So now I can hover over that and I can see that that's deprecated. And it shows up on both the var and the new, because the var is effectively telling me web client again. So in both cases, it's a deprecated type. So those are the three big tools for helping you stay in the rails of what you really mean to be doing. So that's an interesting thing to do as you're writing. If you're writing, currently writing code that's not targeting .NET standard, but you want to prepare yourself for a future where you might, but this analyzer on, it's a green squiggly. It'll still compile. And you're told as you're writing code, guess what? This isn't going to work in .NET standard. It will work perfectly well, targeting the full framework, what you're currently doing. Your app's going to run, but it's letting you know that the code you're writing is not compatible with .NET standard. And it's not going to show you everything that's not compatible with .NET standard, but it will show you all the deprecated stuff, which is a big chunk. So if you put WinForms code in here, that would not be compatible with .NET standard, but you wouldn't get a green squiggly because you would still be targeting .NET full framework to get the WinForms there. All right, cool, yeah. So- Now the big gnarly table that everybody shows- The gnarly table. You want to see the gnarly table? Yes, I do. Okay, well let's come over here and open a new browser window, because I want to actually kind of show people how to find this as well, because we'll put some links up. Yes, we will. They're not always going to come back here. And so if you just say .NET standard version table, okay, that's pretty easy. If you hit enter there, you will see something in the docs. Yeah, you get some tables too. That's awesome. You get some tables, but it's the standard versions.md. Yeah, the .NET standard. We thought that we didn't go far enough making .NET mouse, so we had to make mouse.NET, so we literally made table.NET. Yeah. All right, we're going to ignore the table. There it is. There it is. All right. Do you want to see the pretty one? No. You want to see the ugly one? Is there a pretty one? There's a prettier one. Let's see the pretty one. It's right up here with this little tiny line. This is interactive. Let's go to the interactive one. It's got colors. Okay. Okay. So are you as mystified by this one as the other one? By now, less so, but it's been seen over and over again. You've had this conversation several times. Yes. Okay. Why? What is this telling me? What do I do with this besides go get some aspirin? Okay. Well, this is not as bad as it looks, although I do understand that on first blush, this actually looks pretty crazy. So the first thing is that, I'd like to just like to say that by default, .NET standard 2.0 is green. Good to go. Okay. So .NET standard 2.0 is really where a lot of things came together. The platform support .NET standard 2.0, that's the one that was based on these evaluations of what real code looked like. It wasn't like what somebody thought was going to happen. A lot of stuff happened for .NET standard 2.0 to be the place to be if you can be. Okay. So for you, you're writing WinForms WPF apps, and you're just interested in what full frameworks you can run on. Other than that, you don't care. Right. You're not worried about reach. You're only worried about where you're at at this moment. Yep. So if you are on .NET full framework, 4.6.1 or above, you're good to go. Okay. Because 4.6.1 is in the table next to framework under 2. So you can target .NET standard 2.0, assuming that you're running the actual framework on your production machine is .NET full framework 4.6.1 or above. But not everything in 4.6.1 is in standard 2.0, right? But .NET standard 2.0 is supported by full framework 4.6.1. Okay. So if you, so if you're- Oh, I see. So if you've written- Yeah. So if you, let me say this. Yes. Please do. You tell me if I'm correct. So if you've targeted .NET standard 2.0, and on the machine you have 4.6.1, it will work. It will work. I want to come back- If you only have 4.5.1 on the machine, there are potentially things that you wrote to that aren't in there. But wouldn't your compiler have caught that in the first place? No, because your compiler is looking at netstandard 2.0 DLL, the reference DLL I showed you earlier. So it's compiling against netstandard DLL 2.0, and .NET full framework 4.5.1 does not have a netstandard DLL 2.0. It has a netstandard DLL 1.2, and it says, I can't even start. I can't do anything, try again. And so if you want to, for whatever reason, if you need to target .NET full framework 4.5.1, you would have to use .NET standard 1.2. And for most people, at that point I'd say, what are you going to gain from it? If you can target 2.0, then you're sort of in this nice friendly space. But it's much more painful. I'll show you a little bit about what that pain looks like. So we're going back to 1.2. Oops, I need to be, that's not what I needed to click. So we're going to try it again. We're going to go here and we're going to say 1.2, okay? So now you see all of the things that you can run on. There's a lot of things now that you can actually run on. But do you remember what the blue bar at the top looked like before? It was all the way across. That's like just a little bar graph of what's available to you. So you have 30% of your APIs are available. 70% are not available. So you're going to have problems. You're going to run into something you're doing that is not supported. And so if you have a compelling reason to do that, I can give you one compelling reason. If you were a library author planning on putting something on Nougat, and you wanted as many people as possible to use yours, and you tested with the analyzer I showed or some other way you just targeted to see what happened. And you said, hey, you know what? I can do it. No problem. Everything I want is in there. Then at that point, you can target.NET standard, 1.2, have the broadest possible reach, and you haven't hurt yourself. Right. But for you writing your WinForms or WPF app, I'm going to say, what are you gaining? You know, why are you trying to do this? If you're back here. So 2.0 is really the sweet spot. And I do want to just say with a little caveat that 4.6.1, up until 4.7, the way that the location of things were shifting around on a couple of pieces inside the full framework that caused a bit of headaches for.NET standard. So the.NET standard DLL had to be aligned with what was on the machine. There was a couple of things that it just wasn't quite as solid as you want your production machines to be. So you might want to still target.NET full framework, 4.6.1 or 4.6.2 or 4.7, I guess, and then use that analyzer to see if you're ready to go and then maybe look at actually targeting.NET standard in like the 4.7.1 or 4.7.2 time frame because these shifts around that needed to happen just to get us fully on to.NET standard, they're done. And so there's a little bit of time in there where it was just not as solid as you probably want your production machine to be. It's not, I don't want to scare you on that. It's just that some things moved from out of box to in box and that was a challenge for.NET standard because it was here and now it's there. And a few things like that just wound up with a few problems. And just skipping those problems on production is a great idea. So let's close with how often.NET standard will change. All of the things under here are constantly changing. There's a 4.7 framework. There's a 2.1 core coming out. iOS 11 is out and Visual Studio will have support for it potentially by the time this posts if not soon after that. Android 9 is going to be out eventually. UWP, there's a new version which is a couple of weeks away or so, I'm told. Some of these other things don't change. Will the.NET standard change every time one of these changes? Okay, that's a great question. So first of all, let's be clear that all of those numbers are anything higher than that will also support. So immediately right now, 4.7.1, 2.1 of.NET core which is available in preview right now. All of those things support.NET standard 2.0 right now. So all of the numbers in that column is those or anything greater. So when iOS 11 comes out, then there may be a little bit of work that has to happen if there's again these things. When things move.NET standard has to point to the right spot. The.NET standard DLL that might need a little bit of tweaking. I can't promise that won't happen. But people working very hard for that to be smooth and in not. So would that be a standard 2.01 or a 2.1? Because one of the interesting things is if you remember, all of the curly brackets are empty in the reference DLL. And so.NET standard itself will never have a patch release because there's no code to patch. It only has changes to its API surface layer because it is just an API surface layer. So.NET standard only needs to change when there are APIs that need to be added to it. Which doesn't necessarily happen just because iOS went from version 10 to 11 or Android went from 8 to 9 or UWP went from 10.0, 16 to 99 to 10.0, 17, blah, blah, blah. Right. And so the interesting thing about that, especially for right now because we're in a lot of conversions in so many numbers in the air and it's all very confusing, is that.NET Core is in preview on.NET Core 2.1. It's moving forward, but there haven't been any changes right now to.NET standard. So.NET standard is independent of.NET Core. And it will stay on.NET standard 2.0 for the next foreseeable future, the next few months at least until there's something. So we have span now in.NET Core, updated versions 2.1. .NET Core has span and all of its friends. Is that in standard 2.0? It is not in standard 2.0, but that's the kind of thing that would push.NET standard into.NET standard 2.1. And there's going to be a little bit of a, I think a conversation about whether.NET standard should be aggressive in versioning. And as soon as somebody has something. I got an idea, why don't we look at usage? Grab that. Why don't we go look at that graph? What percentage of existing apps today use span? It's probably a less than system.data.link. So I think there's two. It will increase over time. I think there's two pieces that are super important. One is exactly that. And the other is remember.NET standard in and of itself does not matter. It only matters when platforms support it. So if you create a.NET standard 2.1. And the only thing in the planet that supports it is.NET Core 2.1. Did you gain anything? Because nobody else can use it. So it's not just people using span, but it's also other frameworks being ready to support span or whatever the API is. I'm just using that as an example. And so it's when those kinds of things start happening that we want to see.NET standard evolve. So the new features that I could use, CRUS platform, if you just let me, are in.NET standards. Or have the ability to extend it. Because I believe.NET Core, there's the ability to extend it to call missing pieces of the framework. Is that correct? So there's a couple of things you might be referring to there. One is that there's a compatibility pack, which is misnamed. Which is misnamed. I just want to say that. I had nothing to do with this name. It's called a Windows compatibility pack. So you'd think it was just for Windows, wouldn't you? Yeah, no. About half of it will also run CRUS platform. And half of it will just. So that is a way of adding things that aren't in core and calling them from your code. So you could potentially see something similar for standard. You want span that's not in standard yet. Here's a way to kind of shove it in on the side. So that might happen in the future. Right now, that would wind up being something through Nougat that you would be getting a span that made sense in your world. And as of today, that's not something that I see out there at all. I think that as we get into.NET standard, I mean, our first step is just to explain this crazy thing. And have people understand it and understand why they care. And then we'll see how it evolves as we see what people ask for. As they start really hopefully embracing it and embracing a way that there's no reason to write your application class libraries anymore that are specific to a framework unless there is a reason. So there's no, it used to be that was the only way to write it. And that was not a problem when our frameworks were like all over the map and hitting really different targets. So Windows phone versus full framework, those are really different. But now we have .NET Core and .NET full framework, and they both run on a Windows machine. And you're already figuring out which of those you want to do. And .NET standard gives you a way to say that decision can be a kind of temporary decision. It doesn't have to be a locked in stone decision for your class libraries. Cool. So yeah, that's where we're at today. All right, thanks. I think this cleared up a lot of the confusion. I hope it did. I think I had to see you confused. If I'm confused, you got to imagine the viewers are too. It's not just about me. It's not just about you, Robert. I hope you enjoyed that and we will see you next time on Visual Studio Toolbox.