C# 为什么是typeof(T)!=实例。getType()?

C# 为什么是typeof(T)!=实例。getType()?,c#,generics,casting,C#,Generics,Casting,我正在一家工厂工作,它将根据类型返回接口的通用实现 我的主要问题由 为什么这些类型的(TException)!=异常。GetType()?分别而言,我需要更改什么才能获得正确的TException类型 上述代码导致InvalidCast异常,因为它尝试强制转换到IDocumedisExceptionHandler而不是IDocumedisExceptionHandler internal class FhirParsingExceptionHandler : IDocumedisExceptio

我正在一家工厂工作,它将根据类型返回接口的通用实现

我的主要问题由
为什么这些类型的(TException)!=异常。GetType()?分别而言,我需要更改什么才能获得正确的TException类型

上述代码导致InvalidCast异常,因为它尝试强制转换到
IDocumedisExceptionHandler
而不是
IDocumedisExceptionHandler

internal class FhirParsingExceptionHandler : IDocumedisExceptionHandler<FhirParsingException>
{
    public void HandleException(FhirParsingException exception, out HttpStatusCode httpStatusCode, out OperationOutcome.IssueType issueType, out string message)
    {
        httpStatusCode = HttpStatusCode.BadRequest;
        issueType = OperationOutcome.IssueType.Invalid;
        message = exception.Message;
    }
}
工厂实施:

internal class DocumedisExceptionHandlerFactory : IDocumedisExceptionHandlerFactory
{
    private readonly IDictionary<Type, object> _exceptionHandlers = new ConcurrentDictionary<Type, object>();

    public void RegisterExceptionHandler<TException>(IDocumedisExceptionHandler<TException> exceptionHandler)
        where TException : DocumedisException
    {
        _exceptionHandlers.Add(typeof(TException), exceptionHandler);
    }

    public IDocumedisExceptionHandler<TException> GetDocumedisExceptionHandler<TException>(TException exception)
        where TException : DocumedisException
    {
        _exceptionHandlers.TryGetValue(exception.GetType(), out var exceptionHandler);
        return (IDocumedisExceptionHandler<TException>) exceptionHandler;
    }
}
其中
FhirParsingExceptionHandler
实现
IDocumedisExceptionHandler

internal class FhirParsingExceptionHandler : IDocumedisExceptionHandler<FhirParsingException>
{
    public void HandleException(FhirParsingException exception, out HttpStatusCode httpStatusCode, out OperationOutcome.IssueType issueType, out string message)
    {
        httpStatusCode = HttpStatusCode.BadRequest;
        issueType = OperationOutcome.IssueType.Invalid;
        message = exception.Message;
    }
}
FhirParsingException
扩展
documediseException

public class FhirParsingException : DocumedisException
{
   [...]
}
从中间件检索处理程序:

public async Task Invoke(HttpContext context)
{
   try
   {
      await _next.Invoke(context);
   }
   catch (Exception ex)
   {
      if (ex is DocumedisException documedisException)
      {
         await HandleDocumedisExceptionAsync(context, documedisException);
      }
      else
      {
         throw;
      }
   }
}

private async Task HandleDocumedisExceptionAsync<TException>(HttpContext context, TException ex, MedicationAnalyzerErrorCode? errorCode = null)
   where TException : DocumedisException
{
   var exceptionHandler = _documedisExceptionHandlerFactory.GetDocumedisExceptionHandler(ex);
   [...]
}
公共异步任务调用(HttpContext上下文)
{
尝试
{
wait_next.Invoke(上下文);
}
捕获(例外情况除外)
{
如果(例如是documediseption documediseption)
{
等待处理ocumedisexceptionsync(上下文,documedisException);
}
其他的
{
投掷;
}
}
}
私有异步任务HandleDocuMediaSexceptionAsync(HttpContext上下文,TException ex,MedicalationAnalyzerErrorCode?errorCode=null)
其中TException:documediseption
{
var exceptionHandler=\u documedisExceptionHandlerFactory.GetDocumedisExceptionHandler(ex);
[...]
}
typeof(TException)
提供了
异常的编译时类型
exception.GetType()
提供运行时类型
exception
。这两者不必完全相同,编译器所做的唯一保证是
exception
的运行时类型将可分配给
TException
变量

考虑以下几点:

class Animal { }
class Turtle: Animal { }
bool CheckTypes<T>(T animal) where T: Animal 
{
     return typeof(T) == animal.GetType();
}

请放心,
CheckTypes
将返回
false
;泛型类型参数的类型是
Animal
,但
Animal
的运行时类型实际上是
Turtle

这是否回答了您的问题@帕夫拉尼霍斯基不是真的。它解释了差异,但不是我如何获得正确类型的TException。正如InBetween所解释的,它是在编译时确定的。
IDocumedisExceptionHandler
是如何声明的?是否与
TException
相关?看来,你的问题与泛型有关mostly@PavelAnikhouski它是相反的(只是因为resharper让我这么做)。我已经编辑了这个问题,以包括界面。如果你投的是无效的,它将在协变通用界面的情况下工作。你们应该花一些时间来完善你们当前的方法,并编写代码。这回答了为什么的主要问题,谢谢!但是,我没有找到一种方法来解决我的问题,即从工厂中检索类型化的处理程序,它需要一个确切的异常类型。我可以传递DocumedisException并将其强制转换到处理程序中,但我确实希望避免这种情况,@Philipple显示
IDocumedisExceptionHandler
界面。如果可以使其协变(
IDocumedisExceptionHandler
),则转换应该成功;与
IEnumerable
相同,可以强制转换为
IEnumerable
。如果它是反变的或不变的,那么您将陷入当前设置。我已经按照Pavel的要求添加了接口定义。我将不得不读一些关于协变和逆变的内容。@Philippe接口是逆变的,因此您尝试的演员阵容无效。在我可以支配的时间内,我想不出一种方法使其协变。我将documedesception传递给处理程序,使其成为非泛型。如果需要,处理程序可以将其强制转换。不完美,但功能齐全。
class Animal { }
class Turtle: Animal { }
bool CheckTypes<T>(T animal) where T: Animal 
{
     return typeof(T) == animal.GetType();
}
Animal animal = new Turtle();
Feed(animal);