TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

C#: No, you don’t get to use the “as” operator any more

22 点作者 Indyan大约 14 年前

10 条评论

snprbob86大约 14 年前
Many language designers, including many on Microsoft's Managed Language teams, consider null reference and invalid cast exceptions to be huge blunders.<p>The "Nice" language shows that it's pretty easy to statically avoid this: <a href="http://nice.sourceforge.net/safety.html" rel="nofollow">http://nice.sourceforge.net/safety.html</a><p>The sad fact is that the Java and .NET base class libraries were designed before (1) generics and (2) a generic "Nullable" (aka "Option") type were available. Anyone designing a statically typed environment today should certainly include both and design a compiler to enforce their usage and safety.
评论 #2498904 未加载
评论 #2498925 未加载
评论 #2499121 未加载
mendicant大约 14 年前
Yes, null refs are bad.<p>But so is an InvalidCastException -- Which is what your new code could throw.
评论 #2498803 未加载
评论 #2498962 未加载
jasonkester大约 14 年前
It's best if you think about the reason that "as" was added to C#. It's so you can do this:<p><pre><code> Customer c = person as Customer; if (c != null) { // do something } else { // not a customer. must be just a regular person. do something else } </code></pre> instead of this:<p><pre><code> if (person is Customer) { Customer c = (Customer)person; // do something } else { // not a customer. must be just a regular person. do something else } </code></pre> ... and that's it. It's just somebody's idea of a little cleaner syntax, not having to cast twice to get where you want to be.<p>In that light, the author's second example is closest to correct. It's just missing the "else" bit to handle the case where the base object you get passed is not be the exact type you're looking for.
singular大约 14 年前
EDIT: Actually, yes, <i>ahem</i>, I see - if e.NewItem is actually null you're going to get confused between what the problem actually is here, and that might not be repro. Perhaps I posted a little too soon... but assuming you check for that separately, the point stands :)<p>I have to disagree here - I prefer the initial code example. It's cleaner, and as soon as you get to the line of code in the debugger you'll know exactly what's up regardless of the on-the-surface-misleading null exception. So what if it's initially confusing?<p>In any case both examples are wrong, and I don't think that's made clear enough - you should be <i>actively</i> looking to check for exceptions, not passively accepting that they might happen.<p>As an aside, I've always found it cleaner to say:-<p><pre><code> var cust = e.NewItem as Customer; if(cust == null) throw new BlahException("blah blah blah"); cust.Save(); </code></pre> Compared to, say:-<p><pre><code> if(!(e.NewItem is Customer)) throw new BlahException("blah blah blah"); var cust = (Customer)e.NewItem; cust.Save(); </code></pre> (Note that in the second case that a thread could jump in and spoil your day anyway, not to mention that .NewItem could be some crazy property which randomly decides to return null in the second case, and you'd get the same old nasty exception, as mentioned in other posts)<p>So I think the 'as' operator has value in this alone as handy sugar.<p>Obviously the real problem is that null exceptions happen at all, or that anything actually returns null, and by God is the Option discriminated union in F# a joy (union of Some/None) after dealing with all that shizzle.
noblethrasher大约 14 年前
I would make the public version of Save a static method on an abstract class (or a static method in a utility class) and avoid the whole worry over null. It's only a bit more work up front.<p><pre><code> abstract class Foo { public static Result Save(Foo foo) { if(foo != null) foo._Save(); else { //Do Stuff... } } protected abstract Result _Save(); } </code></pre> Then use like so,<p><pre><code> foreach(Foo s in xs) { Foo.Save(s); //or s.Save() if Save() is an extension method. }</code></pre>
评论 #2499238 未加载
评论 #2499001 未加载
scottdw2大约 14 年前
Actually... he misses a big use case (stolen from haskell)... Using extension methods (which accept null receivers) and "as" you can get pretty readable straight line code... something like:<p><pre><code> name = (obj as Customer).LiftName() ?? "Guy Incognito" </code></pre> Interestingly, built in support for this (w/o the need to write a "LiftName" extension method) almost made it into VB 2008, but it ended up getting cut.
singular大约 14 年前
There are subtleties to it too - <a href="http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-s-the-difference-between-as-and-cast-operators.aspx" rel="nofollow">http://blogs.msdn.com/b/ericlippert/archive/2009/10/08/what-...</a><p>:-)
tomjen3大约 14 年前
I tend to use it because it makes it reading from left to right feel right instead of jumping back and forth.<p>And really, don't give me null objects unless I specifically say I can handle them.
InclinedPlane大约 14 年前
((e.NewItem as Customer) ?? Customer.NullObject).Save();<p>Edit: The idea being, you have a sub-class of Customer which implements the Null Object pattern, which you instantiate through a static member on Customer or a Property method or what-have-you. The great thing about this is that you can tailor the behavior in this situation to whatever you want. Want to throw an exception? Sure, throw whatever exception you want from CustomerNullObject.Save(). Want to log an error and otherwise silently fail? No prob, easy peasy.
k2xl大约 14 年前
strange... ecma script allows it...