2010-05-31 75 views
0

在if结构中调用NotifyObservers的行处,出现以下相关代码片段时出现编译时错误。编译时错误:无法从特定类型转换为通用类型

public class ExternalSystem<TEmployee, TEventArgs> : ISubject<TEventArgs> 
    where TEmployee : Employee 
    where TEventArgs : EmployeeEventArgs 
{ 
    protected List<IObserver<TEventArgs>> _observers = null; 
    protected List<TEmployee> _employees = null; 

    public virtual void AddNewEmployee(TEmployee employee) 
    { 
     if (_employees.Contains(employee) == false) 
     { 
      _employees.Add(employee); 

      string message = FormatMessage("New {0} hired.", employee); 

      if (employee is Executive) 
       NotifyObservers(new ExecutiveEventArgs { e = employee, msg = message }); 
      else if (employee is BuildingSecurity) 
       NotifyObservers(new BuildingSecurityEventArgs { e = employee, msg = message }); 
     } 
    } 

    public void NotifyObservers(TEventArgs args) 
    { 
     foreach (IObserver<TEventArgs> observer in _observers) 
      observer.EmployeeEventHandler(this, args); 
    } 
} 

我收到的错误是:

The best overloaded method match for 'ExternalSystem.NotifyObservers(TEventArgs)' has some invalid arguments. Cannot convert from 'ExecutiveEventArgs' to 'TEventArgs'.

我在使用Visual Studio 2008 Express版本编译此C#3.0。

现在,我已经解决了将特定对象实例化分解为重写方法的问题,如下面给出的代码片段,但我需要理解错误发生的原因。我认为编译器可以推断出上述情况下的类型层次结构。

public class ExternalSystem<TEmployee, TEventArgs> : ISubject<TEventArgs> 
    where TEmployee : Employee where TEventArgs: EmployeeEventArgs 
{ 

protected List<IObserver<TEventArgs>> _observers = null; 
protected List<TEmployee> _employees = null; 

protected virtual void AddNewEmployee(TEmployee employee) 
{ 
    if (_employees.Contains(employee) == false) 
    { 
     _employees.Add(employee); 

     string message = FormatMessage("New {0} hired.", employee); 

     NotifyObservers(GetEventArgs(employee, message)); 
    } 
} 


protected virtual TEventArgs GetEventArgs(TEmployee employee, string message) 
{ 
    return default(TEventArgs); 
} 

public void NotifyObservers(TEventArgs args) 
{ 
    foreach (IObserver<TEventArgs> observer in _observers) 
     observer.EmployeeEventHandler(this, args); 
} 
} 

public class SecuritySystem : 
ExternalSystem<BuildingSecurity, BuildingSecurityEventArgs> 
{ 
    public SecuritySystem() : base() { } 

protected override BuildingSecurityEventArgs GetEventArgs(BuildingSecurity employee, string message) 
{ 
    return new BuildingSecurityEventArgs { msg = message, e = employee }; 
} 

public void HireSecurityGuard(BuildingSecurity buildingSecurity) 
{ 
    this.AddNewEmployee(buildingSecurity); 
} 

public void FireSecurityGuard(BuildingSecurity buildingSecurity) 
{ 
    this.TerminateEmployee(buildingSecurity); 
} 

}

回答

1

TEventArgs泛型参数会出现一些特殊类型,它是从EmployeeEventArgs派生的,但是编译器不知道它的确切类型将是直到后来。因此编译器不能允许转换,因为它不知道它是否有效。

只是为了澄清,如果你创建ExternalSystem<Janitor, JanitorEventArgs>类型的对象,然后TEventArgs将在此对象的上下文JanitorEventArgs,并NotifyObservers两个呼叫将是无效的,因为ExecutiveEventArgs不从JanitorEventArgs派生。

+0

但编译器不知道ExecutiveEventArgs的类型是EmployeeEventArgs? BuildingSecurityEventArgs也是这样吗? – 2010-05-31 09:44:29

+0

@ WC2,是的,但是你试图将它传递给一个方法,该方法需要'TEventArgs',它是_isn't_'EmployeeEventArgs',但是一些未指定的类型派生自'EmployeeEventArgs'。 – 2010-05-31 10:00:01

相关问题