Minor adjustments to the existing time codes in the video description. 0:00 - Intro 1:23 - Creating demo console application 2:36 - What is C# 8? 3:43 - Read-Only Struct Members 13:09 - Default Interface Method Implementations 43:36 - Switch Expressions 51:45 - Using Declarations 59:47 - Indices and Ranges 1:12:07 - Null Coalescing Assignments 1:20:57 - Concluding remarks
Yep, I missed that. The point still stands, which is good, but I made a copy/paste error (which is why I suggest not using copy/paste - I just get impatient in videos).
@@IAmTimCorey yup, the typo of cart instead of cart2 is why they were both the same output, not because it was static in the interface. I was yelling “typo” at the screen, lol.
In some code I'm working on, Visual Studio was recommending I consider using a switch expression instead of switch statement. Yours was the first great explanation-by-example that I found. Many thanks!
Hi Tim, in 29:40 you created a ShoppingCart object named cart2 then you used the other object called cart instead of cart2 to calculate the subtotal. Thats why you were getting the same result.
I would guess the motivation behind using [^1] instead of [^0] is to follow convention established by other languages (such as Python). However using [-1] would have allowed various mistakes in index calculation to resurface. Hence they used a different char for "negative" indices while keeping the convention
super! I got confused by your example of the statics in the interfaces because you first re-used the same variable (cart) in the first case and then changed it (to cart2) in the second case, so it seemed like that was expected behavior, but I see that it actually is still order dependent regardless.
Yes, you cannot access the methods implemented by the interface unless you cast to that interface type. In an abstract class, you will have access to those methods provided by the abstract class even if you use the child class type.
@@IAmTimCorey Yeah, your explained that very well in the video but what me and probably others are wondering is what use this is since we always had a more "clean" way of doing this by having an abstract class implement an interface with the wanted default methods and leave the unwanted implementations abstract for implementations down the line. Works quite well for DI in my opinion.
@@TeamCykelhold You only got one class to inherit from. If you don't have any base class you could use an abstract class, but if you already are inheriting from one this is your only possibility.
time 50:30 i typed the same thing but i am getting an error for the underscore. it says CS1061 'double' does not contain a definition for '_' and no accessible extension method '_' accepting a first argument of type 'double' could be found (are you missing a using directive or an assembly reference?) what should i do?
Tim, this a great video on the new features - although Im a bit late bc I'm relearning c# after a 15 year hiatus. I just finished the Mastercourse and I'm glad I happened to found this. Thank you!
sorry to be offtopic but does someone know a way to log back into an instagram account? I was stupid lost my login password. I would appreciate any tricks you can offer me.
@Bennett Dylan i really appreciate your reply. I found the site thru google and Im trying it out now. Seems to take quite some time so I will get back to you later with my results.
time 1:14:57 in the Program.cs if i put two fuctions like IndicesAndRangesDemo.Demo(); NullCoalescingAssignmentDemo.Demo(); the NullCoalescingAssignmentDemo.Demo(); doesn't work. can u please tell me the reason?
He Tim, Thanks for the video. I have a couple (2) of weird things happening on my computer, though. I started typing along while your video progressed. The first problem that arose, was after having finished typing the entire code in 2-DefaultInterfaceMethods (up to the 20:00 minute mark), I got red squigglies under public class ShoppingCart : IShoppingCart because the void CalculateSubtotal method in the public interface IShoppingCart was not implemented, just like in your video on that time mark, but in your video there were no red squigglies. Therefore I decided to download the source code. That is where the second strange thing happened. I opened the solution in Visual Studio 2019 Community edition, updated yesterday to version 16.3.6. That is where a really strange thing happened, which I did not have in the version I started myself. And that is that the keywords System, void and string give off warning signals that say Cannot resolve symbol ‘x’. Do you know what this could be? Thanks in advance, and keep up the good work!
As an addition, I overlooked another update (did not expect that after having updated just yesterday). I have installed it just now and I am now on 16.3.7. It did not solve the problem, though.
@@IAmTimCorey He Tim. At first it turned out I did not. Then after installing it through the project properties, choose target framework, install other frameworks I got it installed, but to na avail unfortunately. It is still warning me that Interface methods are not implemented and also, having resumed following your video, it doesn't allow me to type the public static void SetDefaultName method. As soon as the word public is typed it gets wiped out. In the project properties on the Build tab click Advanced, the language I'm running is grayed out and a link in the window says Why can't I select a different C# version? As I read it online it actually could not even be anything other than C#8. The things I'm experiencing do not seem to support that however. I'm at a loss.
I installed the Preview version of VS 2019 community on another machine and that works. Since both the dotnet core 3.0 and C# 8 are released, I tried doing all this in non-preveiw version which I felt would work. I was wrong.
The interop is an important reason. Also, the ability to expand your interfaces without making a set of them is an important improvement. The suggestion that every default implementation should throw a NotImplementedException is a good one.
I agree with you @Daniel Whitney, this seems like a train wreck trap. Might allow a team to maintain momentum in a time crunch but has the pitfall of creating hidden technical debt that will never be repaid.
I don't know why, but It's very strange for me to see access modifier or an implementation in an interface. I see it usefulness but it's weird and unappetising for my fingers to write in my code. Now I cannot trust a class that implement a certain interface to actually have implementation to all the methods in that interface. If you have an interface that have methods which you think you don't need to implement, then IMO this interface need to be splitted into two or more smaller interfaces. I agree with you, the only valid use of it that I can think of is when you don't want to break code that someone uses. But again, I will see people misusing it and it will be a pain to deal with. Thank you for the video! I love your content.
I don't understand this using statement without curly braces. As I understand "the old way", it will tell GC explicitly when the variable is out of scope so it can proceed disposing it. But without braces, GC has to decide on its own when the variable is out of scope. So, how is that different opposed to not having using statement at all?
The purpose of a using statement is a bit different than that. The closed curly braces indicate that the processing is done so the Dispose() method can then be called on the variable. Then the variable goes out of scope. When using the using statement without curly braces, the Dispose() method is called when the variable will go out of scope. The key is the Dispose() method being called. If we didn't use a using statement, the Dispose() method would never be called.
@@IAmTimCorey OK I understand your point. I assumed when working with dispose pattern that the dispose method would be called by class finalizer anyways, so using statement would make no difference, but actually, there is a difference. Need to brush up on my c# fundamentals :) Thanks for clarification.
I find that the best way to explain the reason for default interface members is to talk about the way LINQ is implemented on various data types. For example, LINQ Count() can work faster on an IList than a general-purpose IEnumerable, but what about, say, IReadOnlyList? There's no way to reliably add this post-hoc, and it is precisely this problem that default interface members are designed to fix.
I'm confused on the default methods for interfaces. Isn't the purpose of abstract classes to implement some methods? Now interfaces have this feature? Then what's the difference between interfaces and abstract classes now?
Static members on interfaces are actually extremely useful for writing high level syntax parsers. It's a niche, but it's the first thing I thought of. I'm definately refactoring one of my projects thanks to this.
@@IAmTimCorey Although I am considering dropping straight into C#/IL hybrid projects instead (either way the same effect, but there's some other advantages. Working with language is awful. You'd think language people would make a language to make working with language better, but... nah.
I still don't see the point of default interface methods. Why not use an abstract base class? Doesn't this blur the line between abstract classes and interfaces? And strangest of all, what about the most common interview question: "Can an interface have any code in it?" This seems like a useless feature to me, but what do I know?
The cross-platform compatibility with Android libraries and others is one driving factor. Yes, it does blur the lines with an abstract class if you are using it that way, but as I argued, that isn't the way to use this feature. Use it as a way to add to your interfaces without breaking backward compatibility. Yes, this will change the answer to interview questions.
I think the weird line wrapping in the console is due to the console interpreting 0 or 1 spaces in the last 2 columns as meaning that the line continues on the next line. The readonly method / getter modifiers look a lot like C++99's const modifier. Default interface implementations seem to mark the interface methods as non-abstract non-final methods with IL method bodies, and point the target method at the interface method in the interface map when it is not overridden. I don't think there's a way of calling the default implementation from an overriding implementation (trying to call it through reflection just calls the overriding method), so it's not like a base class virtual method.
I've had a problem with using-declarations. I went into a project some of my friends were working on to refactor everything, as well as bring in some C# 8.0 features. There was one method with two using-blocks, which I converted to two using-declarations, but for some reason, this theoretically functional equivalent stopped the method from returning anything useful, and none of us know why. One thing to note is that the second (nested) using-declaration had a dependency on the first.
The dependency is not an issue. My guess is that there was some type of other change that happened to the method at the same time. Put it back like it was and see if it works. If it does, replace just one using statement with a declaration and see if things still work. Keep making single changes until the problem recurs.
@@IAmTimCorey We already did revert the changes taken, but there really should have been no side effects. It works again now, but it remains a mystery.
Reverting is just the first step. Now that it is working (make sure it is), slowly add the changes and test. Don't just add them all back in. Do one at a time and see if it breaks. That will help you narrow down the issue. It is most likely that you are changing the functionality when you didn't expect to.
I really don't understand the thinking about the range with 'up till', when every single 'range' in most languages it is 'up including', so why the sudden change in expected behaviour? Normally when you see [1..4] you'd expect 1, 2, 3 and 4 not 1, 2 and 3.
Hi Tim, Between 30.15 - 30.18 you used “cart” twice in lines 11 and 17 however you should have used “cart2” at line 17 then the result might have been as predicted?
Hi Tim. Great video, as always. Really clearly explained. These all look super powerful. I can understand the default interface declarations, but doubt I'll use them. But the one thing I'm struggling with is that the final item in an indexer really seems like it should be [^0]. It would keep consistency with the first item being [0]. And the range feels like it should be inclusive. [3..5] feels to me like it should return items 3, 4 & 5.
It would seem that way, but there is an explanation for it. Part of it has to do with the fact that other languages do counting the same way. That is the biggest discussion around this feature though.
I don’t get the ‘using’ part. Where does it end?Does its scope end at the end of the method? If so, that’s kinda bummer. Something like below has been valid before C# 8, i guess. Maybe i’m wrong. using (var inst1 = new SomeClass()) using (var inst2 = new AnotherClass()) { // do something } Both ‘using’ end at the same time, i think. No need for nested curly braces. IMO most of these changes are feels like not needed.
The dispose is run when the variable goes out of scope. So, if you declare the variable in a function, then when the function ends, the variables go out of scope, and the dispose is called. I add agree, you don't have to nest usings the way Tim did, in his particular demoware code. But, sometimes you need to do something between the usings.
It is guaranteed to end by the end of the closing curly braces for the method. However, scope is a bit trickier in that once a variable is no longer needed, it can be collected. There isn't clear documentation on it, but I believe the using statement dispose may be triggered after the last time you use the variable. As for your nesting example, yes, in this demo that would have worked but usually there is more going on before and after the nested using statement
The only way you have access to an interface implementation is by referencing that interface so there isn't a "real" problem here. If two interfaces have the same method and each have a default implementation, you would access the one that is in the interface you used. So if you use IUser, you would get the implementation from IUser where if you used IPerson, you would get that implementation. This is when you declare your variable so "IUser tim = new Person();" vs IPerson tim = new Person();"
I'm surprised you didn't cover Nullable reference types. I think that is a huge win for C#. You can almost eliminate run time null reference errors if you use this feature. Of course, enabling it on the brown field app could be problematic.
Probably because it is something you have to opt into even with C# 8 applications and not something that you can just start using out of the box without configuring it on. I agree it is a cool new feature though.
It is a nice new feature. I covered a lot with this video and there were more things that I wanted to cover. That one, though, will come up in a video in the nearish future. Probably a TimCo Retail Manager video, where we turn it on and break stuff.
Great video! Thank you very much for creating it! No. 2 default interface method - as I understand it is useful when a method receives object of type IShoppingCart already but now it needs to do something else, and you already have a tone of classes implementing this interface?
Correct. You don't need to create a new interface, you just use the existing one and add functionality to it. The idea is that then you can go back and use that new functionality in more and more places over time, but until then you can have new content with an old interface.
1. The readonly members is cool. 2. I am not a fan of the default interface methods, and especially not a fan of the default static properties in interfaces. 3. The switch expressions is ok, as long as each case in the switch will always be a simple one line statement, but if something needs to added to the switch at some point that is not one line, then that code block would need to be refactored into a single method call or the entire switch would need to be refactored to be the traditional style. 4. Removing the blocks in the Using Declarations could have some interesting potential in static implementations, otherwise, using code blocks is not bad thing and really helps point back to what is being used. 5. I generally do not care for the python language, but one thing I do really like about it is being able to use negative integers to wrap back to the end of a list. This implementation with the ^ is basically the same thing, but it loses the best part of just being able to use a negative number in an integer variable. One of the things I like least in python is the range being exclusive of the end number, but this kept that bad trait. 6. The null coalescing is ok, but it still requires code to be changed in cases like you demoed. It would have been nice if the language would just generate a NEW instance if the instance is null and if there is a constructor available that does not require any parameters, and then it just give a warning that it had to create it automatically.
Thanks for sharing your thoughts. As to your last point about null coalescing operators, it isn't always true that you just want to new up an instance. You might want to new it up with certain values if it is null. Also, the system cannot assume that an empty-constructor instantiation is what is desired.
Love your explanations but the issue you were having around @30:33 was because you were calling the same instance of 'cart'. If you had used cart2 it likely wouldn't have broken on you. You fixed it later in the video, but didn't come back to identify the problem
I saw a serious problem with your example of using statics in the default interface implementation. I tried an experiment. For my experiment, I created 2 classes and each set to a certain value. However, when i ran the code, it showed the value of the second one on both which is undesirable behavior. Do you know a workaround for that case. I was hoping there was some magic where it somehow used the proper values even though static was used but did not happen.
I demonstrated those issues with static in this video. I showed how order mattered and how you need to think of those static variables as application-wide rather than situational. So you would only set them/use them if the value applied to all situations across your application (which is why I said to avoid them).
Hi, I have watched a lot of your videos and they help me a lot BUT I want to ask something. How do you input for example: public double Length {get;set;} in a second ? It is a fast command like CW,Tab,Tab for Control.WriteLine();.
Type out "prop" and tab twice. It is another code snippet. There is also "propfull", which is similar but for a full property instead of an auto-property.
Hi Tim, really want to appreciate your effort here, these videos are super-helpful. I have one question though, providing default implementation to interface methods frees the class from implementing it, doesn't it violates the interface segregation principal? This way interfaces can easily bloat in a very short period and classes dont care as they dont have to implement them? What are your thoughts on this?
This isn't about bloating an interface and violating ISP. Instead, it is about being able to extend an interface in a logical manner without breaking old implementations. New classes should implement everything. Only existing classes should use the defaults (since they don't call them anyway).
`??=` and `if...` are not 100% the same. The prior one is a expression and has a value. The doc has an example like this: int? a; WriteLine(a??=1); WriteLine(a??=2); This will show 1 and 1. Although I think this way should be avoided and will only make us more confused.
I am feeling ill today, so I'm lying on the sofa, catching up with a bunch of IAmTimCorey videos for fun. I thought I'd watch this one. I was curious about the default implementation of methods in interfaces. You mention that they don't cause a breaking change in the IShoppingCart example, but I see it as a breaking change, and here's why: The implementation of the interface (namely, the ShoppingCart class) doesn't break, it's true, but *calling* code could break. What if you had calling code like this: if (TheCart is IShoppingCart cart) { cart.CalculateSubTotal(); cart.CalculateTotal(); }? If CalculateSubTotal() needs to do something in order for the subtotal to display correctly in the UI, then ShoppingCart won't work properly. I realize that in that case, I shouldn't use a default implementation for CalculateSubTotal, but I'm struggling to find *any* case in which I wouldn't be testing the class from calling code to see if it supports an interface. The only case I can come up with is something like, say, double CalculateTax(), where there's usually no tax, and in that case my default implementation could return 0. Still, though, it's a source of bugs for my code if I forget to update the TenPercentTax class to override CalculateTax() and return SomeAmount * 0.10. I guess my point is, if the default implementation *ever* is incorrect, then I've got potential unforseen bugs in my code, and therefore, not using a default implementation forces me to address all classes that implement the interface. You could argue, correctly, that *any* code change is a potential source of bugs; I just see this one as inviting trouble, I guess. Just my two cents, and I realize not everyone will agree!
Good thoughts. Here is the reason it is not a breaking change: no existing code will break because of the change. Yes, there is new code you can call poorly or the new code could be buggy but only NEW changes will access that code and trigger those bugs. The existing code, until it is changed, will not know about or care about the new methods. That's what a breaking change is - a change that breaks existing code. This won't do that.
Hello tim I had trouble connecting to MySQL php admin with my code using entity framework. When I try to enable migration that’s when the errors pop up. Thank you
Not sure what the issue is. The errors should point you in the right direction. Read them, get the relevant bits and google them to see if you get help that way.
11:48 "don't do that though" lol for some reason I imagine a father saying "you could put your finger in a socket and get shocked...don't do that though"
I like the default interface method feature, but I think this encourages developers to write bad code. I see as a solution for this versioning. just create a folder v2 for example with the same interface but in different namespace. I would only use default interface method where versioning is not possible. greate video as always!
Default interface methods seem like a really bad idea. I hoped interfaces would always be a reliable contract and that changing them SHOULD cause the implementation code to scream at you.
Part of this is the pain we need to deal with in order to have a more compatible ecosystem (one that works with Android and other languages). Part of this is providing options for you. You don't have to provide default implementations. If you don't, you will get yelled at. However, you now have that option instead of being forced into one choice.
Options are not always good. Tools that can be used or misused can be good. Tools that are almost assuredly going to blow up in your face are bad. I feel like I need to add a FxCop rule for this and it would have been better for an opt-in mechanism.
I think you don’t need to upgrade your existing projects. All these changes except the interface one, might save you few lines here and there in your code. Not worth the time and effort.
Thank you for swift reply. I like new switch so wanted to use it in my project. My project is not that big yet so i was thinking to upgrade before will grow bigger. Is it a lots of work to upgrade ? Thank you for your time
"Upgrading" versions of C# has to do mostly with just having the latest version of Visual Studio. However, by default it only is designed to work with .NET Core 3.0 or later. You can force it into lower versions but it isn't advised. It is only .NET Core versions (and .NET Framework versions) that require upgrading your project. As for changing the .NET version of your project, I would encourage you to stay current if it isn't too much trouble because that will keep your application code relevant for longer. However, don't spend so much time upgrading that you don't finish your project.
It looks like an interface became almost a class. It may be confusing when to create a class and inherit from that class and when to create an interface and implement it.
It has a lot more class-like abilities but it is subtly different, which can cause more confusion. In general, use interfaces the way they used to work unless you REALLY need to expand them. You will be a lot happier.
The only disappointing thing is most new features in c# 8.0 does not work with .net standard 2.0. I found from experimenting so far that if a person wanted to use blazor client, then they are forced to use .net standard 2.0 for now.
You can multi-target and force C# 8 into .NET Standard (at least some bits of it). It isn't a great option, though, and it will be a bit before we can use it natively with .NET Standard.
@@IAmTimCorey Actually I found from tests you can use natively with .net standard 2.1. Since I don't do the traditional framework anymore, its no problem that it will not implement the .net standard 2.1. I even ran tests to see if .net standard 2.1 works on xamarin and it does. The only place that does not work for now is if somebody was using blazor client. Once blazor client supports either .net standard 2.1 or the new .net 5 next year, then i can finally move all my code off of .net standard 2.0 and use all the new features of c# 8.0. The good news is switch expressions worked with .net standard 2.0 though.
It doesn't really defeat the purpose (default implementations don't work the same way as abstract classes do). Instead, it just fills a small niche that needed to be addressed (expanding an interface after it is in use without changing all of the items that depend on the interface without the added items).
I think this actually supports OCP. The reason is that your classes that implement the interface already are closed to changes. That would mean that you cannot change the interface. By allowing the interface to have a default implementation, you don't have to change existing classes when you update the interface. That allows you to create new classes that use the updated interface while the existing classes don't break. The key to remember is that the default values really aren't designed to be used. They are designed to not break existing class implementations.
@@IAmTimCorey oh okay thanks was just wondering as in the past i have heard from some people that using ++ or += can impact performance or something negative
I think the default interface implementation is a nice alternative to extension methods (on interface). Also an up side is the class can have their own implementation if they beg a difference with the “extension method”.
Thanks a lot again for this great video. I have used switch expression and using declaration in my project right now it was so fun refactoring and saving lines of code.
By 37min, you started the case of disproving multi-inheritance by implementing multiple interfaces. They you said "now I have multi-inheritance... well, not really". It seems that you don't really know what multiple inheritance means. Your example was implementing 2 interfaces with the same method, both with default implementations. Since default implementations act very similar to explicit implementation, you just showed the obvious: you need to explicitly use the interface type. This is not an example of multiple inheritance. Same method name in different interfaces is at most an example of polymorphism. If you have 2 distinct interfaces A and B, with distinct methods names and default implementations, you can mix them in in a third interface C. This interface C has multi-inherited A and B, like mixins, and then you have you multiple inheritance. It works for interfaces, not for classes, because they are "explicit".
It works for interfaces, not for classes, which means we don't have multi-inheritance. Interfaces don't have inheritance, they have implementation. Now that they have code, they come closer but if they had inheritance they would violate LSP. Classes have inheritance and they don't have multi-inheritance.
Why did you mix up default interface implementations with static side effect nonsense? Now everybody is saying default implementations are a bad idea. The whole example about taxes, it was just a collection of anti-patterns, and five minutes later you admitted them. I think you missed the point regarding the new features and some terrible examples of messing up your code with static instances. Default interface implementations works like explicit interface implementations, which you could have shown. Easier to explain why the method does not show in autocomplete, for example. Well, nevertheless video is great, kudos to you.
Minor adjustments to the existing time codes in the video description.
0:00 - Intro
1:23 - Creating demo console application
2:36 - What is C# 8?
3:43 - Read-Only Struct Members
13:09 - Default Interface Method Implementations
43:36 - Switch Expressions
51:45 - Using Declarations
59:47 - Indices and Ranges
1:12:07 - Null Coalescing Assignments
1:20:57 - Concluding remarks
Thank you! Updated.
at 29:35 did you get confused? Shouldn't the second line be cart2.CalculateSubtotal() instead of cart.CalculateSubtotal()?
Yep, I missed that. The point still stands, which is good, but I made a copy/paste error (which is why I suggest not using copy/paste - I just get impatient in videos).
AyuNeko Yes you are right
@@IAmTimCorey yup, the typo of cart instead of cart2 is why they were both the same output, not because it was static in the interface. I was yelling “typo” at the screen, lol.
Thanks Tim, much appreciated
You are welcome.
Your tutorials are just the best Tim! Easy to understand and rich in information. You have a fan here!!
Thanks!
Well I spent 10 years in c# programming. Loved the video.
Great!
In some code I'm working on, Visual Studio was recommending I consider using a switch expression instead of switch statement. Yours was the first great explanation-by-example that I found. Many thanks!
I am glad it was helpful.
Implementation in an interface definition? Inconceivable!
Yep. It has a purpose, but it isn't for everyday use.
Hi Tim, in 29:40 you created a ShoppingCart object named cart2 then you used the other object called cart instead of cart2 to calculate the subtotal. Thats why you were getting the same result.
Duh! Thanks for pointing that one out.
@@IAmTimCorey You are welcome. Thank you for the great video.
I would guess the motivation behind using [^1] instead of [^0] is to follow convention established by other languages (such as Python). However using [-1] would have allowed various mistakes in index calculation to resurface. Hence they used a different char for "negative" indices while keeping the convention
Another Important Video !!!
Thank you for the endorsement
This video not only taught me C# 8.0 features but lots and lots of other things too, like implicit copy concept etc etc. Thanks Tim.
Excellent!
super! I got confused by your example of the statics in the interfaces because you first re-used the same variable (cart) in the first case and then changed it (to cart2) in the second case, so it seemed like that was expected behavior, but I see that it actually is still order dependent regardless.
Yeah, I didn't see the copy/paste error but it still does cause issues.
If interfaces can have default implementations, what is the difference with abstract classes?
I was wondering the exact same thing...it's like a mix of abstract and interface now...is that really better?
Visibility of the methods without explicitly casting to the interface type he said around 37mn
Yes, you cannot access the methods implemented by the interface unless you cast to that interface type. In an abstract class, you will have access to those methods provided by the abstract class even if you use the child class type.
@@IAmTimCorey Yeah, your explained that very well in the video but what me and probably others are wondering is what use this is since we always had a more "clean" way of doing this by having an abstract class implement an interface with the wanted default methods and leave the unwanted implementations abstract for implementations down the line. Works quite well for DI in my opinion.
@@TeamCykelhold You only got one class to inherit from. If you don't have any base class you could use an abstract class, but if you already are inheriting from one this is your only possibility.
29:31 You had a bug in your code. After you instantiated ShoppingCart you should of invoked `CalculateSubtotal` of the `cart2` object not `cart`.
Yep, I noticed that. That's what I get for copying and pasting.
time 50:30
i typed the same thing but i am getting an error for the underscore. it says
CS1061 'double' does not contain a definition for '_' and no accessible extension method '_' accepting a first argument of type 'double' could be found (are you missing a using directive or an assembly reference?)
what should i do?
My guess is that you forgot a comma on the previous line.
@@IAmTimCorey yeah u were right, i put fullstop instead of comma. thanks
Tim, this a great video on the new features - although Im a bit late bc I'm relearning c# after a 15 year hiatus. I just finished the Mastercourse and I'm glad I happened to found this. Thank you!
You are welcome.
I really like your way of explaining things. I often don't have a time to read all this new things and you do quite nice summaries :)
I am glad they are useful to you.
I disagree, he is far too wordy. Each segment could be half as long and just as useful.
sorry to be offtopic but does someone know a way to log back into an instagram account?
I was stupid lost my login password. I would appreciate any tricks you can offer me.
@Guillermo Kylen instablaster :)
@Bennett Dylan i really appreciate your reply. I found the site thru google and Im trying it out now.
Seems to take quite some time so I will get back to you later with my results.
time 1:14:57
in the Program.cs if i put two fuctions like
IndicesAndRangesDemo.Demo();
NullCoalescingAssignmentDemo.Demo();
the NullCoalescingAssignmentDemo.Demo(); doesn't work. can u please tell me the reason?
Not sure. You would need to debug it.
@@IAmTimCorey oh ok, i will try
He Tim,
Thanks for the video. I have a couple (2) of weird things happening on my computer, though. I started typing along while your video progressed. The first problem that arose, was after having finished typing the entire code in 2-DefaultInterfaceMethods (up to the 20:00 minute mark), I got red squigglies under public class ShoppingCart : IShoppingCart because the void CalculateSubtotal method in the public interface IShoppingCart was not implemented, just like in your video on that time mark, but in your video there were no red squigglies. Therefore I decided to download the source code. That is where the second strange thing happened. I opened the solution in Visual Studio 2019 Community edition, updated yesterday to version 16.3.6. That is where a really strange thing happened, which I did not have in the version I started myself. And that is that the keywords System, void and string give off warning signals that say Cannot resolve symbol ‘x’. Do you know what this could be?
Thanks in advance, and keep up the good work!
As an addition, I overlooked another update (did not expect that after having updated just yesterday). I have installed it just now and I am now on 16.3.7. It did not solve the problem, though.
It sounds like you aren't using C# 8. I know Visual Studio is updated but do you have .NET Core 3.0 installed?
@@IAmTimCorey He Tim. At first it turned out I did not. Then after installing it through the project properties, choose target framework, install other frameworks I got it installed, but to na avail unfortunately. It is still warning me that Interface methods are not implemented and also, having resumed following your video, it doesn't allow me to type the public static void SetDefaultName method. As soon as the word public is typed it gets wiped out. In the project properties on the Build tab click Advanced, the language I'm running is grayed out and a link in the window says Why can't I select a different C# version? As I read it online it actually could not even be anything other than C#8. The things I'm experiencing do not seem to support that however. I'm at a loss.
I installed the Preview version of VS 2019 community on another machine and that works. Since both the dotnet core 3.0 and C# 8 are released, I tried doing all this in non-preveiw version which I felt would work. I was wrong.
interface member cannot have a definition, how come when u define CalculateTotal (20:13) there is no error message??
This is a new feature of C# 8 - default implementations.
@@IAmTimCorey I just started learning c#, so I assume i need to install 3.0 net core in order to use c# 8?
Default interface methods feels like a code smell. I cant imagine a case where it encourages good design
The interop is an important reason. Also, the ability to expand your interfaces without making a set of them is an important improvement. The suggestion that every default implementation should throw a NotImplementedException is a good one.
I agree with you @Daniel Whitney, this seems like a train wreck trap. Might allow a team to maintain momentum in a time crunch but has the pitfall of creating hidden technical debt that will never be repaid.
I don't know why, but It's very strange for me to see access modifier or an implementation in an interface. I see it usefulness but it's weird and unappetising for my fingers to write in my code. Now I cannot trust a class that implement a certain interface to actually have implementation to all the methods in that interface. If you have an interface that have methods which you think you don't need to implement, then IMO this interface need to be splitted into two or more smaller interfaces. I agree with you, the only valid use of it that I can think of is when you don't want to break code that someone uses. But again, I will see people misusing it and it will be a pain to deal with. Thank you for the video! I love your content.
Yep, there is a lot of room for misuse here. The key is to be careful how we use these things.
This is not going to end well!
I don't understand this using statement without curly braces. As I understand "the old way", it will tell GC explicitly when the variable is out of scope so it can proceed disposing it. But without braces, GC has to decide on its own when the variable is out of scope. So, how is that different opposed to not having using statement at all?
The purpose of a using statement is a bit different than that. The closed curly braces indicate that the processing is done so the Dispose() method can then be called on the variable. Then the variable goes out of scope. When using the using statement without curly braces, the Dispose() method is called when the variable will go out of scope. The key is the Dispose() method being called. If we didn't use a using statement, the Dispose() method would never be called.
@@IAmTimCorey OK I understand your point. I assumed when working with dispose pattern that the dispose method would be called by class finalizer anyways, so using statement would make no difference, but actually, there is a difference. Need to brush up on my c# fundamentals :) Thanks for clarification.
I find that the best way to explain the reason for default interface members is to talk about the way LINQ is implemented on various data types. For example, LINQ Count() can work faster on an IList than a general-purpose IEnumerable, but what about, say, IReadOnlyList? There's no way to reliably add this post-hoc, and it is precisely this problem that default interface members are designed to fix.
Thanks for sharing.
I love your way of explaining concepts.
Thank you!
"Is There Multi-Inheritance Now" - such a clickbait XD
lol, yeah, I was wondering what to put for the tag. That seemed appropriate, since that's the question that is getting asked a lot.
@@IAmTimCorey Yeah, that's true. Anyway, thank you for you hard work.
Hi Tim, can you do a video on the ObservableCollection, and on Observables in general?
I will add it to the list. Thanks for the suggestion.
I'm confused on the default methods for interfaces. Isn't the purpose of abstract classes to implement some methods? Now interfaces have this feature? Then what's the difference between interfaces and abstract classes now?
Woah... Answered at 36:11. Lol nevermind.
I'm glad I was able to answer your question.
Static members on interfaces are actually extremely useful for writing high level syntax parsers. It's a niche, but it's the first thing I thought of. I'm definately refactoring one of my projects thanks to this.
Excellent! I'm glad it will be of benefit to you.
@@IAmTimCorey Although I am considering dropping straight into C#/IL hybrid projects instead (either way the same effect, but there's some other advantages.
Working with language is awful. You'd think language people would make a language to make working with language better, but... nah.
I find myself using switch expressions way more than I thought I would. I love the succinctness of them.
I'm glad you are enjoying them.
I still don't see the point of default interface methods. Why not use an abstract base class? Doesn't this blur the line between abstract classes and interfaces? And strangest of all, what about the most common interview question: "Can an interface have any code in it?" This seems like a useless feature to me, but what do I know?
The cross-platform compatibility with Android libraries and others is one driving factor. Yes, it does blur the lines with an abstract class if you are using it that way, but as I argued, that isn't the way to use this feature. Use it as a way to add to your interfaces without breaking backward compatibility. Yes, this will change the answer to interview questions.
Well, your classes may already have all different kinds of base classes, so even if you provide a base class, they often can't inherit from it.
I think the weird line wrapping in the console is due to the console interpreting 0 or 1 spaces in the last 2 columns as meaning that the line continues on the next line.
The readonly method / getter modifiers look a lot like C++99's const modifier.
Default interface implementations seem to mark the interface methods as non-abstract non-final methods with IL method bodies, and point the target method at the interface method in the interface map when it is not overridden. I don't think there's a way of calling the default implementation from an overriding implementation (trying to call it through reflection just calls the overriding method), so it's not like a base class virtual method.
Thanks for sharing.
I've had a problem with using-declarations. I went into a project some of my friends were working on to refactor everything, as well as bring in some C# 8.0 features. There was one method with two using-blocks, which I converted to two using-declarations, but for some reason, this theoretically functional equivalent stopped the method from returning anything useful, and none of us know why.
One thing to note is that the second (nested) using-declaration had a dependency on the first.
The dependency is not an issue. My guess is that there was some type of other change that happened to the method at the same time. Put it back like it was and see if it works. If it does, replace just one using statement with a declaration and see if things still work. Keep making single changes until the problem recurs.
@@IAmTimCorey We already did revert the changes taken, but there really should have been no side effects. It works again now, but it remains a mystery.
Reverting is just the first step. Now that it is working (make sure it is), slowly add the changes and test. Don't just add them all back in. Do one at a time and see if it breaks. That will help you narrow down the issue. It is most likely that you are changing the functionality when you didn't expect to.
Ironically, You and Primative Technology are my two favorite subscriptions!
I'm glad to make it to your top two!
Primative? Did you mean Pragim?
I think the safest way to extend default interface implementations safely is to throw exceptions in each default implementation.
That’s a pretty good plan.
I really don't understand the thinking about the range with 'up till', when every single 'range' in most languages it is 'up including', so why the sudden change in expected behaviour?
Normally when you see [1..4] you'd expect 1, 2, 3 and 4 not 1, 2 and 3.
Hi Tim, Between 30.15 - 30.18 you used “cart” twice in lines 11 and 17 however you should have used “cart2” at line 17 then the result might have been as predicted?
Yep, I believe so.
Hi Tim. Great video, as always. Really clearly explained. These all look super powerful. I can understand the default interface declarations, but doubt I'll use them.
But the one thing I'm struggling with is that the final item in an indexer really seems like it should be [^0]. It would keep consistency with the first item being [0]. And the range feels like it should be inclusive. [3..5] feels to me like it should return items 3, 4 & 5.
It would seem that way, but there is an explanation for it. Part of it has to do with the fact that other languages do counting the same way. That is the biggest discussion around this feature though.
I have a question when So what's the difference between new interfaces and abstract?
I kinda understand but i'm not sure.
Don't think of the new stuff. Use interfaces the way they always were used. This new stuff doesn't change that for 99% of cases.
@@IAmTimCorey Thanks.
Keep going with tutorials please, you are so clear to understand, thanks for what you do for us :)
I appreciate the kind words.
I don’t get the ‘using’ part. Where does it end?Does its scope end at the end of the method? If so, that’s kinda bummer. Something like below has been valid before C# 8, i guess. Maybe i’m wrong.
using (var inst1 = new SomeClass())
using (var inst2 = new AnotherClass())
{
// do something
}
Both ‘using’ end at the same time, i think. No need for nested curly braces.
IMO most of these changes are feels like not needed.
The dispose is run when the variable goes out of scope. So, if you declare the variable in a function, then when the function ends, the variables go out of scope, and the dispose is called.
I add agree, you don't have to nest usings the way Tim did, in his particular demoware code. But, sometimes you need to do something between the usings.
It is guaranteed to end by the end of the closing curly braces for the method. However, scope is a bit trickier in that once a variable is no longer needed, it can be collected. There isn't clear documentation on it, but I believe the using statement dispose may be triggered after the last time you use the variable. As for your nesting example, yes, in this demo that would have worked but usually there is more going on before and after the nested using statement
On using declarations, is there a declaration for a collection type or generic withing a collection?
Can you please explain what you are trying to do and why? The answer is maybe, but I’m not sure I understand what you are trying to accomplish.
Hi, excelent video. A question: you are introducing the Diamond Problem with this Default Interface Members. How's C# is going to handle this?
The only way you have access to an interface implementation is by referencing that interface so there isn't a "real" problem here. If two interfaces have the same method and each have a default implementation, you would access the one that is in the interface you used. So if you use IUser, you would get the implementation from IUser where if you used IPerson, you would get that implementation. This is when you declare your variable so "IUser tim = new Person();" vs IPerson tim = new Person();"
switch expressions seem very nice.
Yeah, I agree.
I'm surprised you didn't cover Nullable reference types. I think that is a huge win for C#. You can almost eliminate run time null reference errors if you use this feature.
Of course, enabling it on the brown field app could be problematic.
Probably because it is something you have to opt into even with C# 8 applications and not something that you can just start using out of the box without configuring it on. I agree it is a cool new feature though.
It is a nice new feature. I covered a lot with this video and there were more things that I wanted to cover. That one, though, will come up in a video in the nearish future. Probably a TimCo Retail Manager video, where we turn it on and break stuff.
That's really weird that it did not output the text in two separate lines @30:10
Yeah, right? I'm going to dig into why that is.
Great video! Thank you very much for creating it!
No. 2 default interface method - as I understand it is useful when a method receives object of type IShoppingCart already but now it needs to do something else, and you already have a tone of classes implementing this interface?
Correct. You don't need to create a new interface, you just use the existing one and add functionality to it. The idea is that then you can go back and use that new functionality in more and more places over time, but until then you can have new content with an old interface.
Thanks Tim! Love your videos!
Glad you like them!
1. The readonly members is cool.
2. I am not a fan of the default interface methods, and especially not a fan of the default static properties in interfaces.
3. The switch expressions is ok, as long as each case in the switch will always be a simple one line statement, but if something needs to added to the switch at some point that is not one line, then that code block would need to be refactored into a single method call or the entire switch would need to be refactored to be the traditional style.
4. Removing the blocks in the Using Declarations could have some interesting potential in static implementations, otherwise, using code blocks is not bad thing and really helps point back to what is being used.
5. I generally do not care for the python language, but one thing I do really like about it is being able to use negative integers to wrap back to the end of a list. This implementation with the ^ is basically the same thing, but it loses the best part of just being able to use a negative number in an integer variable. One of the things I like least in python is the range being exclusive of the end number, but this kept that bad trait.
6. The null coalescing is ok, but it still requires code to be changed in cases like you demoed. It would have been nice if the language would just generate a NEW instance if the instance is null and if there is a constructor available that does not require any parameters, and then it just give a warning that it had to create it automatically.
Thanks for sharing your thoughts. As to your last point about null coalescing operators, it isn't always true that you just want to new up an instance. You might want to new it up with certain values if it is null. Also, the system cannot assume that an empty-constructor instantiation is what is desired.
Thanks much Tim for all value you are offering. Hope you reach 1 lakh subscribers in 2019 :)
Thank you!
When you write names[1..] for instance, what does it return? Is it just a view on the original array, or is it a new array object?
I believe it returns the original array.
5:15 “class vs struct = heap vs stack” - that’s actually a very common misconception. eg. a struct in a class is obviously 🙄 in the heap.
Were we talking about nested data structures?
Please explain what and why of defensive copy
I will add it to the list. Thanks for the suggestion.
We need a video about C# 9 please Tim . thanks always
It will come once C# 9 is out. Right now it is just in preview.
Very informative video, thank you Tim! Watched the entire thing :)
You are welcome.
Love your explanations but the issue you were having around @30:33 was because you were calling the same instance of 'cart'. If you had used cart2 it likely wouldn't have broken on you. You fixed it later in the video, but didn't come back to identify the problem
Yeah, one of those copy/paste errors that I should have caught but was too close to see it.
17:45 - coppied text from other mettod to make it faster, and changed almost whole text manually :D
LOL - yup.
I saw a serious problem with your example of using statics in the default interface implementation. I tried an experiment. For my experiment, I created 2 classes and each set to a certain value. However, when i ran the code, it showed the value of the second one on both which is undesirable behavior. Do you know a workaround for that case. I was hoping there was some magic where it somehow used the proper values even though static was used but did not happen.
I demonstrated those issues with static in this video. I showed how order mattered and how you need to think of those static variables as application-wide rather than situational. So you would only set them/use them if the value applied to all situations across your application (which is why I said to avoid them).
Good work Tim !!! Like always Tim :D
Thank you!
Hi, I have watched a lot of your videos and they help me a lot BUT I want to ask something.
How do you input for example: public double Length {get;set;} in a second ? It is a fast command like CW,Tab,Tab for Control.WriteLine();.
Type out "prop" and tab twice. It is another code snippet. There is also "propfull", which is similar but for a full property instead of an auto-property.
Hi Tim, really want to appreciate your effort here, these videos are super-helpful. I have one question though, providing default implementation to interface methods frees the class from implementing it, doesn't it violates the interface segregation principal? This way interfaces can easily bloat in a very short period and classes dont care as they dont have to implement them? What are your thoughts on this?
This isn't about bloating an interface and violating ISP. Instead, it is about being able to extend an interface in a logical manner without breaking old implementations. New classes should implement everything. Only existing classes should use the defaults (since they don't call them anyway).
I think default interface complicate things more with serious problems and bugs
The only way it causes problems is if you abuse it. I'm not sure how it could cause bugs, though.
`??=` and `if...` are not 100% the same. The prior one is a expression and has a value. The doc has an example like this:
int? a; WriteLine(a??=1); WriteLine(a??=2);
This will show 1 and 1.
Although I think this way should be avoided and will only make us more confused.
I wasn't saying that the if statement was equivalent to the ??=, I was saying the if statement and the code inside it were equivalent.
Thanks a lot! That's pretty clear!
You are welcome.
I am feeling ill today, so I'm lying on the sofa, catching up with a bunch of IAmTimCorey videos for fun. I thought I'd watch this one. I was curious about the default implementation of methods in interfaces. You mention that they don't cause a breaking change in the IShoppingCart example, but I see it as a breaking change, and here's why: The implementation of the interface (namely, the ShoppingCart class) doesn't break, it's true, but *calling* code could break. What if you had calling code like this: if (TheCart is IShoppingCart cart) { cart.CalculateSubTotal(); cart.CalculateTotal(); }? If CalculateSubTotal() needs to do something in order for the subtotal to display correctly in the UI, then ShoppingCart won't work properly. I realize that in that case, I shouldn't use a default implementation for CalculateSubTotal, but I'm struggling to find *any* case in which I wouldn't be testing the class from calling code to see if it supports an interface. The only case I can come up with is something like, say, double CalculateTax(), where there's usually no tax, and in that case my default implementation could return 0. Still, though, it's a source of bugs for my code if I forget to update the TenPercentTax class to override CalculateTax() and return SomeAmount * 0.10. I guess my point is, if the default implementation *ever* is incorrect, then I've got potential unforseen bugs in my code, and therefore, not using a default implementation forces me to address all classes that implement the interface. You could argue, correctly, that *any* code change is a potential source of bugs; I just see this one as inviting trouble, I guess. Just my two cents, and I realize not everyone will agree!
Good thoughts. Here is the reason it is not a breaking change: no existing code will break because of the change. Yes, there is new code you can call poorly or the new code could be buggy but only NEW changes will access that code and trigger those bugs. The existing code, until it is changed, will not know about or care about the new methods. That's what a breaking change is - a change that breaks existing code. This won't do that.
Is C# 8.0 available only in .NET core or also in .NET framework?
As of 2021
I believe it is Core-only.
Hello tim
I had trouble connecting to MySQL php admin with my code using entity framework. When I try to enable migration that’s when the errors pop up.
Thank you
Not sure what the issue is. The errors should point you in the right direction. Read them, get the relevant bits and google them to see if you get help that way.
Hi Tim, any plans for videos about CQRS?
It is on the suggestion list. It isn't terribly high right now just because there are so many things to cover yet.
CQRS with MediatR or Event Sourcing.
11:48 "don't do that though" lol for some reason I imagine a father saying "you could put your finger in a socket and get shocked...don't do that though"
Pretty much.
I like the default interface method feature, but I think this encourages developers to write bad code. I see as a solution for this versioning. just create a folder v2 for example with the same interface but in different namespace. I would only use default interface method where versioning is not possible. greate video as always!
Thanks for sharing that suggestion
Default interface methods seem like a really bad idea. I hoped interfaces would always be a reliable contract and that changing them SHOULD cause the implementation code to scream at you.
Part of this is the pain we need to deal with in order to have a more compatible ecosystem (one that works with Android and other languages). Part of this is providing options for you. You don't have to provide default implementations. If you don't, you will get yelled at. However, you now have that option instead of being forced into one choice.
Now we have implementation in Interfaces, they need to change the Interface definition. Now “the contract” between interface and class is broken... :)
Yeah, it is messy.
I started my own channel after being inspired by you. Thanks!
Excellent!
@@IAmTimCorey Thank you..:)
some of these new features give the programmers more possibilities to practice writing bad code and end up eventually with unmaintainable code
True but options are good. We always have the option to abuse code, but now we get more options to write good code as well.
Options are not always good. Tools that can be used or misused can be good. Tools that are almost assuredly going to blow up in your face are bad. I feel like I need to add a FxCop rule for this and it would have been better for an opt-in mechanism.
Thank you. Your videos are great. It helps me a lot
Glad to hear that!
Hi Tim another super tutorial. Can you also make video or let me know how to upgrade existing all project/solutions safely to c# 8.0. Thank you
I think you don’t need to upgrade your existing projects. All these changes except the interface one, might save you few lines here and there in your code. Not worth the time and effort.
Thank you for swift reply. I like new switch so wanted to use it in my project. My project is not that big yet so i was thinking to upgrade before will grow bigger. Is it a lots of work to upgrade ? Thank you for your time
Luke S not that much of a problem. I’m just lazy. If your project is not that big it’ll be that much easy, i think.
"Upgrading" versions of C# has to do mostly with just having the latest version of Visual Studio. However, by default it only is designed to work with .NET Core 3.0 or later. You can force it into lower versions but it isn't advised. It is only .NET Core versions (and .NET Framework versions) that require upgrading your project. As for changing the .NET version of your project, I would encourage you to stay current if it isn't too much trouble because that will keep your application code relevant for longer. However, don't spend so much time upgrading that you don't finish your project.
Hi Tim, Thank you for your reply. I will upgrade as you suggested.
Do you have to be a paid subscriber in order to download the source code?
Not for most videos. Just click the link in the description, enter your first name and email address, and the source code will be emailed to you.
@@IAmTimCorey I did that yesterday and this morning. Still no email. BTW enjoyed the videos!
If you are missing an email, send me an email directly at tim@iamtimcorey.com and I'll get you the download.
It looks like an interface became almost a class. It may be confusing when to create a class and inherit from that class and when to create an interface and implement it.
It has a lot more class-like abilities but it is subtly different, which can cause more confusion. In general, use interfaces the way they used to work unless you REALLY need to expand them. You will be a lot happier.
I'm on 12th minute and I already subscribed! Damn he is good at sharing the knowledge
Great! I'm glad you are getting value out of the content.
Someone at Microsoft, let's confuse the lot and save some lines of code..
Thanks for the video Tim
It's more than about saving lines of code. Some of it has to do with working in a larger ecosystem (Android, etc.)
Anyone think that switch expressions look a lot like Rust's match expression?
I'm not really familiar with Rust's syntax.
The only disappointing thing is most new features in c# 8.0 does not work with .net standard 2.0. I found from experimenting so far that if a person wanted to use blazor client, then they are forced to use .net standard 2.0 for now.
You can multi-target and force C# 8 into .NET Standard (at least some bits of it). It isn't a great option, though, and it will be a bit before we can use it natively with .NET Standard.
@@IAmTimCorey Actually I found from tests you can use natively with .net standard 2.1. Since I don't do the traditional framework anymore, its no problem that it will not implement the .net standard 2.1. I even ran tests to see if .net standard 2.1 works on xamarin and it does. The only place that does not work for now is if somebody was using blazor client. Once blazor client supports either .net standard 2.1 or the new .net 5 next year, then i can finally move all my code off of .net standard 2.0 and use all the new features of c# 8.0. The good news is switch expressions worked with .net standard 2.0 though.
.net doesn’t “Compile the c#”. It’s a framework library to do useful things with c#
I'm not sure I said .NET compiles C#, but the .NET compiler does.
Great resource.
Thank you!
Wouldn’t having default implementation of an interface defeat the purpose of interfaces because they are abstract
It doesn't really defeat the purpose (default implementations don't work the same way as abstract classes do). Instead, it just fills a small niche that needed to be addressed (expanding an interface after it is in use without changing all of the items that depend on the interface without the added items).
It feels like Default Interface methods break O in SOLID
I think this actually supports OCP. The reason is that your classes that implement the interface already are closed to changes. That would mean that you cannot change the interface. By allowing the interface to have a default implementation, you don't have to change existing classes when you update the interface. That allows you to create new classes that use the updated interface while the existing classes don't break. The key to remember is that the default values really aren't designed to be used. They are designed to not break existing class implementations.
Great tutorial always love watching your videos just a question is their any reason as to why you use var += 1 over var++ or is it just a habit?
I prefer +=1 because it allows me to easily change to another number but it really is just a preference.
@@IAmTimCorey oh okay thanks was just wondering as in the past i have heard from some people that using ++ or += can impact performance or something negative
Can you talk about Azure Data Studio with SQL Server? “Thanks for watching. As always...”
I will add it to the list. Thanks for the suggestion.
Thank you!
You are welcome.
Thanks!
No problem!
I think the default interface implementation is a nice alternative to extension methods (on interface). Also an up side is the class can have their own implementation if they beg a difference with the “extension method”.
Thanks a lot again for this great video. I have used switch expression and using declaration in my project right now it was so fun refactoring and saving lines of code.
You are welcome.
Thanks
You are welcome.
I think default implementations in interfaces is a very bad idea.
Many folks may agree with you.
Default implementations in interfaces should always throw a NotImplementedException.
I won't say always, but I agree that this should be the default.
1:04:08 Do
CTRL + D
Yep, I just forget that one because I don't use it very often.
@@IAmTimCorey but thats good. programmer shouldnt copy paste
Yes.!
well... i was hyped until i realised i should need to cast it as the interface
Right - it isn't multi-inheritance and not really meant to be abused to be that.
Thank you
You are welcome.
By 37min, you started the case of disproving multi-inheritance by implementing multiple interfaces. They you said "now I have multi-inheritance... well, not really". It seems that you don't really know what multiple inheritance means.
Your example was implementing 2 interfaces with the same method, both with default implementations. Since default implementations act very similar to explicit implementation, you just showed the obvious: you need to explicitly use the interface type.
This is not an example of multiple inheritance. Same method name in different interfaces is at most an example of polymorphism.
If you have 2 distinct interfaces A and B, with distinct methods names and default implementations, you can mix them in in a third interface C. This interface C has multi-inherited A and B, like mixins, and then you have you multiple inheritance. It works for interfaces, not for classes, because they are "explicit".
It works for interfaces, not for classes, which means we don't have multi-inheritance. Interfaces don't have inheritance, they have implementation. Now that they have code, they come closer but if they had inheritance they would violate LSP. Classes have inheritance and they don't have multi-inheritance.
Why did you mix up default interface implementations with static side effect nonsense? Now everybody is saying default implementations are a bad idea.
The whole example about taxes, it was just a collection of anti-patterns, and five minutes later you admitted them. I think you missed the point regarding the new features and some terrible examples of messing up your code with static instances.
Default interface implementations works like explicit interface implementations, which you could have shown. Easier to explain why the method does not show in autocomplete, for example.
Well, nevertheless video is great, kudos to you.
Default implementations are a bad idea in most cases. There is a limited use-case, which I explained.