Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 协变赋值不起作用_C#_.net_System.reactive - Fatal编程技术网

C# 协变赋值不起作用

C# 协变赋值不起作用,c#,.net,system.reactive,C#,.net,System.reactive,我试图通过IObservable来概括对象属性更改的通知,但这不是问题的重点。问题的重点是:我将以下赋值报告为无效协方差错误: protected virtual void OnPropertyChanged<T>( string propertyName, T oldValue, T newValue) { IPropertyChangedNotification<Student

我试图通过
IObservable
来概括对象属性更改的通知,但这不是问题的重点。问题的重点是:我将以下赋值报告为无效协方差错误:

protected virtual void OnPropertyChanged<T>(
                      string propertyName, 
                      T oldValue, T newValue)
{
    IPropertyChangedNotification<Student, object> notification = 
        new PropertyChangedNotification<Student, T>(this,
        propertyName, oldValue, newValue);

    ...
}
受保护的虚拟void OnPropertyChanged(
字符串propertyName,
T旧值,T新值)
{
IPropertyChangedNotification通知=
新物业变更通知(本、,
propertyName、oldValue、newValue);
...
}
报告如下:

无法隐式转换类型
PropertyChangedNotification
IPropertyChangedNotification
。存在显式转换(是否缺少强制转换?)

以下是完整的代码:

class Student
{
    private ISubject<IPropertyChangedNotification<Student, object>> _subject = 
       new Subject<IPropertyChangedNotification<Student, object>>();;
    private string _name = null;

    public string Name
    {
        get
        {
            return _name;
        }
        set
        {

            var oldValue = _name;
            _name = value;

            OnPropertyChanged<string>("Name", oldValue, _name);
        }
    }

    protected virtual void OnPropertyChanged<T>(string propertyName, T oldValue, T newValue)
    {
        IPropertyChangedNotification<Student, object> notification = 
            new PropertyChangedNotification<Student, T>(this,
            propertyName, oldValue, newValue);

        _subject.OnNext(notification);
    }
}

public class PropertyChangedNotification<TDeclaringType, TPropertyType>
    : IPropertyChangedNotification<TDeclaringType, TPropertyType>
{
    public PropertyChangedNotification(TDeclaringType declaringObject, 
        string propertyName, 
        TPropertyType oldValue, 
        TPropertyType newValue)
    {
        DeclaringObject = declaringObject;
        PropertyName = propertyName;
        OldValue = oldValue;
        NewValue = newValue;
    }

    public TDeclaringType DeclaringObject { get; set; }
    public string PropertyName { get; set; }

    public TPropertyType OldValue { get; protected set; }
    public TPropertyType NewValue { get; protected set; }
}

public interface IPropertyChangedNotification<TDeclaringType, out TPropertyType>
{
    TDeclaringType DeclaringObject { get; set; }
    string PropertyName { get; set; }

    TPropertyType OldValue { get; }
    TPropertyType NewValue { get; }
}
班级学生
{
私有ISubject _subject=
新主题;;
私有字符串_name=null;
公共字符串名
{
得到
{
返回_name;
}
设置
{
var oldValue=_name;
_名称=值;
OnPropertyChanged(“名称”、“旧值”、“名称”);
}
}
受保护的虚拟void OnPropertyChanged(字符串propertyName、T oldValue、T newValue)
{
IPropertyChangedNotification通知=
新物业变更通知(本、,
propertyName、oldValue、newValue);
_主题.OnNext(通知);
}
}
公共类属性更改通知
:i属性更改通知
{
公共财产变更通知(TDeclaringType declaringObject,
字符串propertyName,
TPropertyType旧值,
TPropertyType(新值)
{
DeclaringObject=DeclaringObject;
PropertyName=PropertyName;
OldValue=OldValue;
NewValue=NewValue;
}
公共TDeclaringType DeclaringObject{get;set;}
公共字符串PropertyName{get;set;}
公共TPropertyType OldValue{get;protected set;}
公共TPropertyType NewValue{get;protected set;}
}
公共接口IPropertyChangedNotification
{
TDeclaringType DeclaringObject{get;set;}
字符串PropertyName{get;set;}
TPropertyType旧值{get;}
TPropertyType新值{get;}
}

PS:这不是生产代码。只需练习即可。

协方差和逆变仅支持引用类型(要将值类型转换为
对象,需要将其装箱)

因此,您需要将
T
约束到
class

void OnPropertyChanged<T>(string propertyName, T oldValue, T newValue)
    where T : class { ... }
然后在
主题
中使用它(因为在订阅时无论如何都必须将其转换为具体类型):

ISubject

!=<代码>
。你为什么需要第一个?只需使用
var
。正如前面指出的
object
=<代码>T。作为一组旁注;尽量避免使用主题。出于兴趣,将INPC事件转化为可观测序列已经有十几种方法解决了;-)这里有一些免费的@LeeCampbell:谢谢你,李。我读了你的文章,很喜欢。我试着用我自己的方式去做。我正在尝试做各种排列和组合,做你书中所有的例子,然后再做一些我自己做的。:-)如果我错了,请纠正我,但参数
object!=T
不适用于接口中的协变泛型类型参数
tpropertyChangedNotification,其中TPropertyType:class
?碰巧将
TPropertyType
限制为引用类型对我没有好处。当然,但是您的代码没有
where-TPropertyType:class
子句。糟糕!有没有一种便宜的方法呢?取决于你所说的便宜是什么意思。我建议的两种选择都不贵。为什么需要键入通知类?无论如何,当你订阅时,你必须使用演员阵容。
public interface IPropertyChangedNotification<TDeclaringType>
{
    TDeclaringType DeclaringObject { get; set; }
    string PropertyName { get; set; }
}

public interface IPropertyChangedNotification<TDeclaringType, out TPropertyType>
    :  IPropertyChangedNotification<TDeclaringType>
{
    TPropertyType OldValue { get; }
    TPropertyType NewValue { get; }
}
ISubject<IPropertyChangedNotification<Student>>