C# 一般方法给出了错误

C# 一般方法给出了错误,c#,generics,C#,Generics,我试图为下面提到的代码片段编写一个通用方法,但它在OrderBy子句中给出了错误?你能告诉我为什么吗 var cache = RedisConnectorHelper.Connection.GetDatabase(); var values = JsonConvert.DeserializeObject<List<StateListDto>>(cache.StringGet(AppConsts.States)); if (values != null) return ne

我试图为下面提到的代码片段编写一个通用方法,但它在
OrderBy
子句中给出了错误?你能告诉我为什么吗

var cache = RedisConnectorHelper.Connection.GetDatabase();
var values = JsonConvert.DeserializeObject<List<StateListDto>>(cache.StringGet(AppConsts.States));
if (values != null) return new ListResultOutput<StateListDto>(values.OrderBy(o => o.Name).ToList());
它给出了以下错误:(单击以查看全尺寸图像)


如果您希望使用它的目的不仅仅是
StateListDto
,我建议您创建一个接口或基类,该接口或基类的属性名为
Name
,那么您可以保证它存在

比如:

public interface IDto
{
    string Name { get; }
}
然后您可以将方法更改为:

public ListResultOutput<T> GetCache<T>(string cacheKey) where T: IDto
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.ToList().OrderBy(o=>o.Name)) : null;
}
public ListResultOutput GetCache(字符串缓存键),其中T:IDto
{
var cache=RedisConnectorHelper.Connection.GetDatabase();
var values=JsonConvert.DeserializeObject(cache.StringGet(cacheKey));
返回值!=null?新建ListResultOutput(values.ToList().OrderBy(o=>o.Name)):null;
}

如果您希望使用它的目的不仅仅是
StateListDto
,我建议您创建一个接口或基类,该接口或基类的属性名为
Name
,那么您可以保证它存在

比如:

public interface IDto
{
    string Name { get; }
}
然后您可以将方法更改为:

public ListResultOutput<T> GetCache<T>(string cacheKey) where T: IDto
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.ToList().OrderBy(o=>o.Name)) : null;
}
public ListResultOutput GetCache(字符串缓存键),其中T:IDto
{
var cache=RedisConnectorHelper.Connection.GetDatabase();
var values=JsonConvert.DeserializeObject(cache.StringGet(cacheKey));
返回值!=null?新建ListResultOutput(values.ToList().OrderBy(o=>o.Name)):null;
}
但所有这些都有名称属性

然后为他们创建一个公共接口,如下所示:

public interface INamed
{
    string Name { get; }
}
public ListResultOutput<T> GetCache<T>(string cacheKey, Func<T,object> selector)
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.OrderBy(selector).ToList()) : null;
}
所有具有该属性的模型都可以实现该接口:

public class StateListDto : INamed
然后可以将该接口用作泛型方法上的类型约束:

public ListResultOutput<T> GetCache<T>(string cacheKey) where T: INamed
public ListResultOutput GetCache(字符串缓存键),其中T:INamed
这样,编译器可以保证
T
的类型将具有
Name
属性

请注意,也可以使用基类(具体或抽象)来完成此任务。虽然我个人更喜欢使用接口而不是继承,除非有特定的理由使用继承

但所有这些都有名称属性

然后为他们创建一个公共接口,如下所示:

public interface INamed
{
    string Name { get; }
}
public ListResultOutput<T> GetCache<T>(string cacheKey, Func<T,object> selector)
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.OrderBy(selector).ToList()) : null;
}
所有具有该属性的模型都可以实现该接口:

public class StateListDto : INamed
然后可以将该接口用作泛型方法上的类型约束:

public ListResultOutput<T> GetCache<T>(string cacheKey) where T: INamed
public ListResultOutput GetCache(字符串缓存键),其中T:INamed
这样,编译器可以保证
T
的类型将具有
Name
属性


请注意,也可以使用基类(具体或抽象)来完成此任务。尽管就我个人而言,我更喜欢使用接口而不是继承,除非有特定的理由使用继承。

您可以将您想要订购的方式作为如下参数发送:

public interface INamed
{
    string Name { get; }
}
public ListResultOutput<T> GetCache<T>(string cacheKey, Func<T,object> selector)
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.OrderBy(selector).ToList()) : null;
}
public ListResultOutput GetCache(字符串缓存键,函数选择器)
{
var cache=RedisConnectorHelper.Connection.GetDatabase();
var values=JsonConvert.DeserializeObject(cache.StringGet(cacheKey));
返回值!=null?新的ListResultOutput(values.OrderBy(selector.ToList()):null;
}
呼叫:

GetCache(“yourKey”,i=>i.Name);

通过这种方式,您不必强制类实现任何东西,您可以选择按代码中的其他参数排序

您可以将您想要排序的方式作为如下参数发送:

public interface INamed
{
    string Name { get; }
}
public ListResultOutput<T> GetCache<T>(string cacheKey, Func<T,object> selector)
{
    var cache = RedisConnectorHelper.Connection.GetDatabase();
    var values = JsonConvert.DeserializeObject<List<T>>(cache.StringGet(cacheKey));
    return values != null ? new ListResultOutput<T>(values.OrderBy(selector).ToList()) : null;
}
public ListResultOutput GetCache(字符串缓存键,函数选择器)
{
var cache=RedisConnectorHelper.Connection.GetDatabase();
var values=JsonConvert.DeserializeObject(cache.StringGet(cacheKey));
返回值!=null?新的ListResultOutput(values.OrderBy(selector.ToList()):null;
}
呼叫:

GetCache(“yourKey”,i=>i.Name);

通过这种方式,您不必强制类实现任何东西,您可以选择按代码中的其他参数排序

“泛型”代码不能保证
t
具有
Name
属性。您可以将
where T:statelistdt添加到
约束中,但不清楚这是否正确。@DStanley那么我如何解决这个问题呢?有什么建议吗?这是什么通用方法?应该支持哪些类型?您的代码不是通用的。您是否希望对任何
T
执行该方法?如果
T
没有
Name
属性怎么办?无论如何,正确的解决方案是删除最后一行,直接返回
值。排序不是
GetCache
的责任。“通用”代码不能保证
T
具有
Name
属性。您可以将
where T:statelistdt添加到
约束中,但不清楚这是否正确。@DStanley那么我如何解决这个问题呢?有什么建议吗?这是什么通用方法?应该支持哪些类型?您的代码不是通用的。您是否希望对任何
T
执行该方法?如果
T
没有
Name
属性怎么办?无论如何,正确的解决方案是删除最后一行,直接返回
值。排序不是
GetCache
的责任。我是否需要在我所有的
dto
上实现此
接口?@Sampath您将在所有希望使用此方法的
dto
上实现。如果您根本不需要它,那么根据Davids Answer的说法,也许可以为接口命名一个更好的名称,如
INamed
。我是否需要在我所有的
DTO
上实现此
接口。如果您根本不需要它,那么根据Davids answer,也许可以为接口提供一个更好的名称,如
INamed
,您能告诉我如何调用此方法吗?GetCache(“yourKey”,i=>i.name);非常感谢。这就是我需要的。完美的解决方案f