C# 如何使功能更强大?

C# 如何使功能更强大?,c#,f#,C#,F#,我是一个c#人,最近学习了JavaScript,并考虑走f#路。我喜欢JavaScript的功能性,但很难将其应用到我的c代码中。我看了下面的代码块,感觉真的很难看。对于那些天生热衷于函数式编程的人来说,用c(甚至f)来完成这一块的更好方法是什么 (或者我是不是找错了地方想改进它) // ///根据tenantNameOverride获取当前租户(如果存在), ///否则,使用urlHost来解决这个问题 ///独立案例 ///如果urlHost和tenantNameOverride为空,则 /

我是一个c#人,最近学习了JavaScript,并考虑走f#路。我喜欢JavaScript的功能性,但很难将其应用到我的c代码中。我看了下面的代码块,感觉真的很难看。对于那些天生热衷于函数式编程的人来说,用c(甚至f)来完成这一块的更好方法是什么

(或者我是不是找错了地方想改进它)

//
///根据tenantNameOverride获取当前租户(如果存在),
///否则,使用urlHost来解决这个问题
///独立案例
///如果urlHost和tenantNameOverride为空,则
///抛出异常
///如果指定了tenantNameOverride但未找到
///抛出异常
///如果未指定tenantNameOverride,则
///没有默认租户,则引发异常
/// 
/// 
/// 
/// 
/// 
私有静态租户GetTenantBasedOnUrlHost(
列出租户,字符串urlHost=null,
字符串tenantNameOverride=null)
{
if(String.IsNullOrEmpty(urlHost)&&
String.IsNullOrEmpty(租户名称覆盖))
{
抛出新的ApplicationException(
“必须指定URL主机或租户名称”);
}
租户;
if(String.IsNullOrEmpty(tenantNameOverride))
{
租户=租户。
FirstOrDefault(a=>a.DomainName.ToLower().Equals(urlHost))??
tenants.FirstOrDefault(a=>a.Default);
if(租户==null)
{
抛出新的ApplicationException
(“必须指定租户名称,未找到默认租户”);
}
}
其他的
{
租户=租户。第一个或默认值
(a=>a.Name.ToLower()==tenantNameOverride.ToLower());
if(租户==null)
{
抛出新的ApplicationException
(“指定了租户名称,但未找到”);
}
}
归还承租人;
}
/*********************更新如下*****************/

根据Jon Skeet的建议,我提出了两种方法。除了顶部的空字符串冲突错误检查之外,我不确定我们在c#中是否可以轻松避免。抛出一个异常在NotFound上也感觉有点奇怪,但是出于我的目的,这些方法应该总是找到一个租户,如果不是的话,这是意外的,异常似乎是合理的

这看起来更干净,更符合单一责任的设计准则。也许这就是我不喜欢我的解决方案的原因,它与功能性或非功能性无关

     /// <summary>
    /// Return tenant based on URL (or return default tenant if exists)
    /// </summary>
    /// <param name="tenants"></param>
    /// <param name="urlHost"></param>
    /// <returns></returns>
    private static Tenant GetTenantBasedOnUrl(
        List<Tenant> tenants, string urlHost)
    {
        if (String.IsNullOrEmpty(urlHost))
        {
            throw new ApplicationException(
                "urlHost must be specified");
        }

        var tenant = tenants.
            FirstOrDefault(a => a.DomainName.ToLower().Equals(urlHost)) ??
                     tenants.FirstOrDefault(a => a.Default);
        if (tenant == null)
        {
            throw new ApplicationException
                ("tenant not found based on URL, no default found");
        }
        return tenant;
    }

    /// <summary>
    /// Get exact tenant name match and do not return default even 
    /// if exists.
    /// </summary>
    /// <param name="tenants"></param>
    /// <param name="tenantNameOverride"></param>
    /// <returns></returns>
    private static Tenant GetTenantByName(List<Tenant> tenants,
        string tenantNameOverride)
    {
        if (String.IsNullOrEmpty(tenantNameOverride))
        {
            throw new ApplicationException(
                "tenantNameOverride or tenantName must be specified");
        }

        var tenant = tenants.FirstOrDefault
            (a => a.Name.ToLower() == tenantNameOverride.ToLower());
        if (tenant == null)
        {
            throw new ApplicationException
                ("No tenant Found (not checking for default)");
        }
        return tenant;
    }
}
//
///基于URL返回租户(如果存在,则返回默认租户)
/// 
/// 
/// 
/// 
私有静态租户GetTenantBasedOnUrl(
列出租户,字符串URL(主机)
{
if(String.IsNullOrEmpty(urlHost))
{
抛出新的ApplicationException(
“必须指定URL主机”);
}
var tenant=租户。
FirstOrDefault(a=>a.DomainName.ToLower().Equals(urlHost))??
tenants.FirstOrDefault(a=>a.Default);
if(租户==null)
{
抛出新的ApplicationException
(“根据URL未找到租户,未找到默认值”);
}
归还承租人;
}
/// 
///获取精确的租户名称匹配,并且不返回默认值
///如果存在。
/// 
/// 
/// 
/// 
私有静态租户GetTenantByName(列出租户,
字符串tenantNameOverride)
{
if(String.IsNullOrEmpty(tenantNameOverride))
{
抛出新的ApplicationException(
“必须指定tenantNameOverride或tenantName”);
}
var tenant=tenants.FirstOrDefault
(a=>a.Name.ToLower()==tenantNameOverride.ToLower());
if(租户==null)
{
抛出新的ApplicationException
(“未找到租户(未检查默认值)”;
}
归还承租人;
}
}

以下是我如何处理F#中的问题

首先,如果我正确理解了需求,那么函数的调用方必须提供域名或租户名称来搜索。在C#中,这种排他规则很难建模,这导致至少必须指定一个规则,但如果两个都指定了,则其中一个参数优先

虽然使用C#的类型系统很难定义这样的规则,但在F#中使用一个有区别的并集来声明是很简单的:

类型租户标准=
|Uri的域名
|字符串名称
这意味着搜索租户的条件可以是
DomainName
或名称,但决不能同时是两者

在我对
DomainName
的定义中,我将类型更改为
System.Uri
。在处理URL时,通常使用
Uri
值比
string
值更安全

与其将
string
值转换为小写,不如使用
StringComparison.OrdinalIgnoreCase
比较它们,如果您需要的话,因为如果您将土耳其字符串转换为小写,会出现各种微妙的本地化问题(这种转换是有损的)

最后,我将查询更改为返回
租户选项
,而不是抛出异常。在函数式编程中,我们更喜欢避免异常。如果您想要比
选项
更详细的异常处理,您可以

综上所述,下面是查找租户功能的一个可能实现:

让findTenant租户=函数
|域名u->
让t=tenants |>List.tryFind(乐趣x->x.DomainName=u)
匹配
|一些t->一些t
|无->租户>
     /// <summary>
    /// Return tenant based on URL (or return default tenant if exists)
    /// </summary>
    /// <param name="tenants"></param>
    /// <param name="urlHost"></param>
    /// <returns></returns>
    private static Tenant GetTenantBasedOnUrl(
        List<Tenant> tenants, string urlHost)
    {
        if (String.IsNullOrEmpty(urlHost))
        {
            throw new ApplicationException(
                "urlHost must be specified");
        }

        var tenant = tenants.
            FirstOrDefault(a => a.DomainName.ToLower().Equals(urlHost)) ??
                     tenants.FirstOrDefault(a => a.Default);
        if (tenant == null)
        {
            throw new ApplicationException
                ("tenant not found based on URL, no default found");
        }
        return tenant;
    }

    /// <summary>
    /// Get exact tenant name match and do not return default even 
    /// if exists.
    /// </summary>
    /// <param name="tenants"></param>
    /// <param name="tenantNameOverride"></param>
    /// <returns></returns>
    private static Tenant GetTenantByName(List<Tenant> tenants,
        string tenantNameOverride)
    {
        if (String.IsNullOrEmpty(tenantNameOverride))
        {
            throw new ApplicationException(
                "tenantNameOverride or tenantName must be specified");
        }

        var tenant = tenants.FirstOrDefault
            (a => a.Name.ToLower() == tenantNameOverride.ToLower());
        if (tenant == null)
        {
            throw new ApplicationException
                ("No tenant Found (not checking for default)");
        }
        return tenant;
    }
}