直列式';试试';用C#可能吗?
是否可以以某种方式调用C#中的内联直列式';试试';用C#可能吗?,c#,exception,exception-handling,try-catch,C#,Exception,Exception Handling,Try Catch,是否可以以某种方式调用C#中的内联try语句 我正在为我的网站检测语言,有时,由于某种原因,客户端的语言类似于en GR。NET抛出异常。所以我需要使用try和catch,即使我没有真正捕捉到任何东西 在这种情况下,这似乎是一种完全的矫枉过正 // Set allowed languages string[] allowedLanguages = { "en", "fr", "ru" }; // Get all possible values var routeLanguage = (filt
try
语句
我正在为我的网站检测语言,有时,由于某种原因,客户端的语言类似于en GR
。NET抛出异常。所以我需要使用try
和catch
,即使我没有真正捕捉到任何东西
在这种情况下,这似乎是一种完全的矫枉过正
// Set allowed languages
string[] allowedLanguages = { "en", "fr", "ru" };
// Get all possible values
var routeLanguage = (filterContext.RouteData.Values["lang"] != null && allowedLanguages.Contains(filterContext.RouteData.Values["lang"].ToString())) ? filterContext.RouteData.Values["lang"].ToString() : null;
var cookieLanguage = (filterContext.HttpContext.Request.Cookies["lang"] != null && allowedLanguages.Contains(filterContext.HttpContext.Request.Cookies["lang"].Value)) ? filterContext.HttpContext.Request.Cookies["lang"].Value : null;
string clientLanguage = null;
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
}
catch (Exception)
{
}
编辑
我无法修复异常,因为我无法控制用户在其区域性信息中的内容。NET只是将en FR视为无效语句。您是否尝试过完全删除
try/catch
语句
string clientLanguage = null;
var userLanguages = filterContext.HttpContext.Request.UserLanguages;
if (userLanguages != null && userLanguages.Length > 0)
{
var culture = CultureInfo
.GetCultures(CultureTypes.AllCultures)
.FirstOrDefault(
x => string.Equals(
x.Name,
userLanguages[0].Name,
StringComparison.OrdinalIgnoreCase
)
);
if (culture != null)
{
clientLanguage = culture.TwoLetterISOLanguageName;
}
}
仅在处理无法控制的异常时使用try/catch。顾名思义,异常应用于处理异常情况
在本例中,您正在执行标准解析,因此最好执行防御性编程,而不是尝试、抛出、捕获 你所做的是正确的方法。你说过,为什么你不能摆脱这个异常(我假设是这样)。所以你必须处理它。唉,C#没有一个try-catch作为表达式(不确定该如何工作——catch“子句”需要返回一个值)
或者,您可以构建一个小助手函数,该函数接受
Func
,调用它并将值传递给调用者。如果发生异常,它将返回(例如)default(T)
。这样可以消除大量的混乱,并且可以重复使用。首先,最好先弄清楚如何避免异常。首先集中精力。抛出该异常是有原因的,如果您可以确定它是什么,那么就不要这样做
要真正回答您的问题:没有现成的“吃掉此表达式中的所有异常”机制,但构建自己的机制很简单:
static T EatExceptions(Func<T> func)
{
try { return func(); } catch { }
return default(T);
}
...
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ?
EatExceptions(() => new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName) :
null; }
静态T异常(Func Func)
{
尝试{return func();}catch{}
返回默认值(T);
}
...
clientLanguage=(filterContext.HttpContext.Request.UserLanguages!=null)?
EatExceptions(()=>new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0])。TwoLetterIsLanguageName):
空;}
如果有人试图在我正在审阅的代码中使用这样的诡计,那么我会。。。好吧,我们只能说,更改不会被签入。99%的时候,吃这样的食物是一个非常糟糕的主意。再一次:找出你做错了什么并停止做它。不要做错事,然后处理失败。好吧,撇开关于预检查的(好)建议不谈,有几种相当普通/平淡无奇/显而易见的方法可以做到这一点:
首先,您可以将其包装在函数中。我想这对你来说还不够普遍
或者,您可以折叠catch
分支:
try
{
clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; // Exception sometimes without `try`
} catch (Exception) { }
或者,你可以把整个东西折叠成一行:
try { clientLanguage = (filterContext.HttpContext.Request.UserLanguages != null) ? new CultureInfo(filterContext.HttpContext.Request.UserLanguages[0]).TwoLetterISOLanguageName : null; } catch (Exception) { }
不优雅,但简单,而且有效。首先尽量避免例外情况。仅仅因为字符串来自您无法控制的源,并不意味着您无法验证它 如果无法避免,则应捕获预期的特定异常,并将该逻辑封装到方法中。不要捕获所有异常 例如:
public static CultureInfo TryGetCultureByName(string name)
{
try
{
return new CultureInfo(name);
}
catch(CultureNotFoundException)//Only catching CultureNotFoundException
{
return null;
}
}
这样,如果您以后发现更好的方法来处理此特定错误,您可以轻松地替换它
例如,您可以创建一个字典
,从CultureInfo.GetCultures()
中填充它,并使用TryGetValue
查找区域性,而不会引发异常
_.Try(() => __YourStatementHere__ );
使用一个像这样的小助手类:
/// <summary>
/// Other utility functions.
/// </summary>
public static class _ {
/// <summary>
/// Tries to execute the given action. If it fails, nothing happens.
/// </summary>
public static void Try(Action action) {
try {
action();
}
catch {
}
}
}
//
///其他实用功能。
///
公共静态类{
///
///尝试执行给定的操作。如果失败,则什么也不会发生。
///
公共静态无效尝试(操作){
试一试{
动作();
}
抓住{
}
}
}
我知道,这个解决方案也不是最优的,但到目前为止,它是我能找到的最简洁的解决方案。我已经构建了一个在线的try-catch机制,可以满足这个目的。我想要一种类似LINQ或回调函数-y的语法。这是通过使用两个包装器、一个TryWrapper和一个CatchWrapper来完成的,这样点操作符就可以适当地提示下一步,隐式地转换为T类型 你也可以这样做
Try(() => UpdateSweetGreen("21", SweetGreen))
.Catch(LogToDb(e.Message))
.Catch(LogToFile(e.Message).Finally(ReportNewSweetGreen(SweetGreen);
基本上,CatchWrapper扩展了TryWrapper。因此,您可以从另一个catch块捕获异常。在本例中,将方法的故障记录到数据库中,然后如果该故障记录到文件中,则不管如何,都会将SweetGreen变量报告给其他组件
这一切都是从TryWrapper开始的
公共类TryWrapper
{
受保护的内部T结果{get;set;}=default(T);
受保护的内部异常异常{get;set;}=null;
公共静态隐式运算符T(TryWrapper包装器)
{
返回包装器.Result;
}
公共静态隐式运算符异常(TryWrapper包装器)
{
返回包装器.Exception;
}
}
和CatchWrapper,它只是扩展了TryWrapper,不能直接调用,只能在尝试后出现,正如您在标准实现中所期望的那样
公共类CatchWrapper:TryWrapper
{
}
然后提出了一系列的静态扩展方法
public static TryWrapper Try(Func-Func)
{
var product=新TryWrapper();
尝试
{
product.Result=func.Invoke();
}
捕获(例外e)
{
product.Exception=e;
}
退货产品;
}
公共静态TryWrapper Try(操作操作)
{
var product=新TryWrapper();
尝试
public class TryWrapper<T>
{
protected internal T Result { get; set; } = default(T);
protected internal Exception Exception { get; set; } = null;
public static implicit operator T(TryWrapper<T> wrapper)
{
return wrapper.Result;
}
public static implicit operator Exception(TryWrapper<T> wrapper)
{
return wrapper.Exception;
}
}
public class CatchWrapper<T> : TryWrapper<T>
{
}
public static TryWrapper<T> Try<T>(Func<T> func)
{
var product = new TryWrapper<T>();
try
{
product.Result = func.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static TryWrapper<T> Try<T>(Action action)
{
var product = new TryWrapper<T>();
try
{
action.Invoke();
}
catch (Exception e)
{
product.Exception = e;
}
return product;
}
public static CatchWrapper<T> Catch<T>(this TryWrapper<T> wrapper, Action<Exception> response)
{
if (wrapper.Exception is null) return wrapper as CatchWrapper<T>;
response.Invoke(wrapper);
wrapper.Exception = null;
return wrapper as CatchWrapper<T>;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action<T> response)
{
response.Invoke(wrapper);
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Func<T> response)
{
wrapper.Result = response.Invoke();
return wrapper;
}
public static TryWrapper<T> Finally<T>(this TryWrapper<T> wrapper, Action response)
{
response.Invoke();
return wrapper;
}