我在我的项目中使用的通用性,但我不知道,有没有什么缺点使用它们,请告诉我一个情况下,他们有一个缺点?我下面code部分。
公共类GenericResult< T>
{
公共t个数据{获得;组; }
公共BOOL IsSuccess {获得;组; }
公共字符串信息{获得;组; }
}
公共GenericResult< INT> AddCategory(t类别t类别)
{
GenericResult< INT>结果=新GenericResult<诠释>();
//业务逻辑验证,不有意义,唯才是举:)
如果(tCategory.Name.Lenght→100)
{
result.IsSuccess = FALSE;
result.Message =类别名称的长度太长;
result.Data = 0;
}
//处理.NET运行时错误//可能是数据库不是aviable。
尝试
{
result.Data = this.catalogRepository.AddCategory(t类别);
result.IsSuccess =真;
}
赶上(例外前)
{
result.Data = 0;
result.IsSuccess = FALSE;
result.Message = ex.Message;
}
返回结果;
}
公共GenericResult< IEnumerable的< t类别>> GetCategoryHierarchy(t类别parentCategory)
{
GenericResult< IEnumerable的< t类别>>结果=新GenericResult< IEnumerable的< t类别>>();
尝试
{
IEnumerable的< t类别> allCategories = catalogRepository.GetAllCategories();
result.Data = GetCategoryHierarchy(allCategories,parentCategory);
result.IsSuccess =真;
}
赶上(例外前)
{
result.IsSuccess = FALSE;
result.Data = NULL;
result.Message = ex.Message;
}
返回结果;
}
解决方案
如果你不想抛出一个异常,而是preFER返回包含任何错误或即也许这很好在某些情况下。但要在这种情况下,我倒是preFER简单地抛出/穿过异常老实。
我preFER像你一样返回一个可变类的不可变结构作为也许
代替。这非常类似于可空< T>
,但它适用于引用类型和可存储一个错误。是这样的:
公共结构或许< T>
{
私人的T值;
私人异常错误;
公共BOOL hasValue的{{返回错误== NULL;}}
公众吨价
{
如果(错误!= NULL)
抛出的错误;
其他
返回值;
}
公共静态也许< T> CreateError(例外的例外)
{
返回新的可能< T>(默认值(T),除外);
}
公共静态也许< T> CreateValue(T值)
{
返回新的可能< T>(值null);
}
公共静态隐含的运营商可能< T>(吨价)
{
返回CreateValue(值);
}
公共重写字符串的ToString()
{
如果(hasValue的)
回报的价值:+ Value.ToString();
其他
回归错误:+ Error.GetType()名++返回Error.message。
}
}
您code变为
公共也许< INT> AddCategory(t类别t类别)
{
尝试
{
返回this.catalogRepository.AddCategory(t类别);
}
赶上(例外前)
{
返回或许< INT> .CreateError(前);
}
返回结果;
}
公众也许< IEnumerable的< t类别>> GetCategoryHierarchy(t类别parentCategory)
{
尝试
{
IEnumerable的< t类别> allCategories = catalogRepository.GetAllCategories();
返回allCategories;
}
赶上(例外前)
{
返回或许< INT> .CreateError(前);
}
返回结果;
}
一个问题,我这个执行看到的是,异常是不可完全不可改变的。这可能会导致问题,如果在同一个也许< T>
抛出的多个线程。也许有人能提出一个更好的实现。
i use generic properties on my project,but i dont know,is there any disadvantage use them,please tell me a scenario,they have a disadvantage?my part of code below.
public class GenericResult<T>
{
public T Data { get; set; }
public bool IsSuccess { get; set; }
public string Message { get; set; }
}
public GenericResult<int> AddCategory(TCategory tCategory)
{
GenericResult<int> result = new GenericResult<int>();
//business logic validation,dont make sense,only example :)
if (tCategory.Name.Lenght > 100)
{
result.IsSuccess = false;
result.Message = "Category Name length is too long";
result.Data = 0;
}
//handle .net runtime error//may be database is not aviable.
try
{
result.Data = this.catalogRepository.AddCategory(tCategory);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.Data = 0;
result.IsSuccess = false;
result.Message = ex.Message;
}
return result;
}
public GenericResult<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory)
{
GenericResult<IEnumerable<TCategory>> result = new GenericResult<IEnumerable<TCategory>>();
try
{
IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories();
result.Data = GetCategoryHierarchy(allCategories, parentCategory);
result.IsSuccess = true;
}
catch (Exception ex)
{
result.IsSuccess = false;
result.Data = null;
result.Message = ex.Message;
}
return result;
}
解决方案
If you don't want to throw an exception but prefer to return a result containing either the error or the value i.e. a MayBe
that's fine in some situations. But to be honest in this situation I'd prefer simply throwing/passing through the exception.
I'd prefer returning an immutable struct as MayBe
instead of a mutable class like you did. It's very similar to Nullable<T>
, except it works on reference types and can store an error. Something like:
public struct MayBe<T>
{
private T value;
private Exception error;
public bool HasValue{get{return error==null;}}
public T Value
{
if(error!=null)
throw error;
else
return value;
}
public static MayBe<T> CreateError(Exception exception)
{
return new MayBe<T>(default(T),exception);
}
public static MayBe<T> CreateValue(T value)
{
return new MayBe<T>(value,null);
}
public static implicit operator MayBe<T>(T value)
{
return CreateValue(value);
}
public override string ToString()
{
if(HasValue)
return "Value: "+Value.ToString();
else
return "Error: "+Error.GetType().Name+" "+Error.Message;
}
}
Your code becomes
public MayBe<int> AddCategory(TCategory tCategory)
{
try
{
return this.catalogRepository.AddCategory(tCategory);
}
catch (Exception ex)
{
return MayBe<int>.CreateError(ex);
}
return result;
}
public MayBe<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory)
{
try
{
IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories();
return allCategories;
}
catch (Exception ex)
{
return MayBe<int>.CreateError(ex);
}
return result;
}
One problem I see with this implementation is that exceptions are not completely immutable. That can cause problems if the same MayBe<T>
throws on multiple threads. Perhaps someone can suggest a better implementation.