neo*_*862 21 c# generics exception
我正在尝试编写一个帮助器方法,该方法将记录消息并使用相同的消息抛出指定类型的异常.我有以下内容:
private void LogAndThrow<TException>(string message, params object[] args) where TException : Exception, new()
{
message = string.Format(message, args);
Logger.Error(message);
throw new TException(message);
}
Run Code Online (Sandbox Code Playgroud)
在添加new()约束之前,编译器抱怨说没有它我无法实例化TException.现在我收到的错误消息是"在创建类型参数'TException'的实例时无法提供参数".我尝试使用无参数构造函数创建实例,然后设置Message属性,但它是只读的.
这是语言的限制还是我不知道的解决方案?也许我可以使用反射,但这对于这么简单的任务来说太过分了.(而且非常丑陋,但这是个人观点的问题.)
Don*_*nut 14
您可以使用Activator.CreateInstance()(允许您传入参数)来创建实例TException.然后,你可以抛出创建的TException.
例如:
private void LogAndThrow<TException>(string message, params object[] args) where TException : Exception, new()
{
message = string.Format(message, args);
Logger.Error(message);
TException exception = (TException)Activator.CreateInstance(typeof(TException), message);
throw exception;
}
Run Code Online (Sandbox Code Playgroud)
是的,这是一个限制; 没有语言结构.
在这种情况下,我的建议是为每个类型的构造函数创建一个类型化的委托; 缓存该委托(为方便起见,通常在泛型类型的静态字段中)并重新使用它.我可以稍后提供一个例子 - 但我不能从iPod做到这一点;)
我相信我已经为Jon Skeet的MiscUtil库提供了一些代码; 所以你也可以在那里看看.
根据要求(评论),这是一种方法 - 在这种情况下使用ExpressionAPI.特别注意嵌套泛型类的使用,确保每个类型组合最多进行一次反射/编译:
using System;
using System.Linq.Expressions;
class Program {
static void Main() {
var ctor = TypeFactory.GetCtor<int, string, DemoType>();
var obj = ctor(123, "abc");
Console.WriteLine(obj.I);
Console.WriteLine(obj.S);
}
}
class DemoType {
public int I { get; private set; }
public string S { get; private set; }
public DemoType(int i, string s) {
I = i; S = s;
}
}
static class TypeFactory {
public static Func<T> GetCtor<T>() { return Cache<T>.func; }
public static Func<TArg1, T> GetCtor<TArg1, T>() { return Cache<T, TArg1>.func; }
public static Func<TArg1, TArg2, T> GetCtor<TArg1, TArg2, T>() { return Cache<T, TArg1, TArg2>.func; }
private static Delegate CreateConstructor(Type type, params Type[] args) {
if(type == null) throw new ArgumentNullException("type");
if(args == null) args = Type.EmptyTypes;
ParameterExpression[] @params = Array.ConvertAll(args, Expression.Parameter);
return Expression.Lambda(Expression.New(type.GetConstructor(args), @params), @params).Compile();
}
private static class Cache<T> {
public static readonly Func<T> func = (Func<T>)TypeFactory.CreateConstructor(typeof(T));
}
private static class Cache<T, TArg1> {
public static readonly Func<TArg1, T> func = (Func<TArg1, T>)TypeFactory.CreateConstructor(typeof(T), typeof(TArg1));
}
private static class Cache<T, TArg1, TArg2> {
public static readonly Func<TArg1, TArg2, T> func = (Func<TArg1, TArg2, T>)TypeFactory.CreateConstructor(typeof(T), typeof(TArg1), typeof(TArg2));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3300 次 |
| 最近记录: |