C# 在强制转换两个相同的对象时无法强制转换对象

C# 在强制转换两个相同的对象时无法强制转换对象,c#,asp.net,entity-framework,linq,casting,C#,Asp.net,Entity Framework,Linq,Casting,在我的模型中,我有三个相同的类视图:UViews、TotalConfiguration和StatsViewModel。它们各自具有相同的属性: public class Views { public int idProject {get;set;} public int January { get; set; } public int February { get; set; } public int March { ge

在我的模型中,我有三个相同的类视图:UViews、TotalConfiguration和StatsViewModel。它们各自具有相同的属性:

 public class Views
    {
        public int idProject {get;set;}
        public int January { get; set; }
        public int February { get; set; }
        public int March { get; set; }
        public int April { get; set; }
        public int May { get; set; }
        public int June { get; set; }
        public int July { get; set; }
        public int August { get; set; }
        public int September { get; set; }
        public int October { get; set; }
        public int November { get; set; }
        public int December { get; set; }
    }
我想通过上下文从视图、UViews或TotalConfiguration的数据库中获取数据,并将结果保存到列表类型StatsViewModel:

//some code

var customer = _context.Get<UViews>(x => x.Projects.ProjectsUser.Where(x => x.IdUser == userId).Any());

//some code

public StatsViewModel Get<T>(Expression<Func<T, bool>> predicate)
   where T : class
        {
            List<StatsViewModel> listItem = new List<StatsViewModel>();
            StatsViewModel item = new StatsViewModel();

            var listFromDatabase = Set<T>().Where(predicate).ToList();
            listItem.AddRange(listFromDatabase.Cast<StatsViewModel>());

            item = listItem.FirstOrDefault();
            return item;
        }
我尝试这样做,但在这种情况下,我得到了相同的错误:

var listFromDatabase = Set<T>().Where(predicate).ToList().Cast<StatsViewModel>();

从编译器的角度来看,这些类型没有任何共同之处。仅仅因为两种类型具有相同的属性,并不意味着它们具有相同的类型。这一点变得更加清楚,因为类通常也有方法。你怎么能指出两个类有相同的方法?想象一下这两个:

class ClassA
{
    int MyProperty { get; set; }
    void DoSomething() => { Console.WriteLine(MyProperty); }
}
class ClassB
{
    int MyProperty { get; set; }
    void DoSomething() => { Console.WriteLine("Hello world"); }
}
上述两个类是否因为成员相同而相等?很难说。当然它们的属性是匹配的,但是它们的方法呢?这两个相等吗?嗯,从形式上看,仅仅考虑到他们的签名,人们可能会这样认为。然而,他们做的事情却各不相同。因此,编译器不可能假设您的两个类型是否实际代表同一事物,这就是为什么它不隐含地允许这样的转换

然而,你还有很多其他的机会。最简单的方法是创建一些映射函数:

ClassA Map(ClassB b) => new ClassA { MyProperty = b.MyProperty };
现在你可以这样称呼它:

myList.Select(x => Map(x));
另一种方法是复制构造函数:

class ClassA
{
    public ClassA(ClassB b) { this.MyProerty = b.MyProperty }
}
您可以使用此Select语句调用它:

myList.Select(x => new ClassA(x));
最后,您可以引入一些隐式或显式转换:

static explicit operator ClassA(ClassB b) => new ClassA { MyProperty = b.MyProperty };
哪一个是唯一可以用于演员阵容的:

myList.Select(x => (ClassA)x);
但是请注意,从IEnumerable调用泛型转换不会反映用户定义的转换。因此,上述三种解决方案中的任何一种仍然不适用于以下内容:

myList.Cast<ClassA>();

最后,我找到了类似JsonConvert的东西,并在代码中使用了它:

public StatsViewModel Get<T>(Expression<Func<T, bool>> predicate) where T : class
   {
      StatsViewModel item = new StatsViewModel();
      var listFromDatabase = Set<T>().Where(predicate).ToList();
            
      List<StatsViewModel> targetlst = JsonConvert.DeserializeObject<List<StatsViewModel>>
      (JsonConvert.SerializeObject(listFromDatabase));

      item = targetlst.FirstOrDefault();
      return item;
   }

C不做duck类型。不同类的对象具有相同的属性是不够的——它们仍然是不同的类型。您可能正在寻找类似Automapper的东西。从编译器的角度来看,您的三种类型没有任何共同之处。然而,从语义的角度来看。。。您可以引入自定义强制转换运算符,并使用Selectx=>MyTypex而不是.cast。@HimBromBeere cast基本上在内部执行MyTypex。@DavidG也用于用户定义的强制转换吗?我怀疑不是这样。@himbrombere你所说的用户定义类型转换是什么意思?我说的是
public StatsViewModel Get<T>(Expression<Func<T, bool>> predicate) where T : class
   {
      StatsViewModel item = new StatsViewModel();
      var listFromDatabase = Set<T>().Where(predicate).ToList();
            
      List<StatsViewModel> targetlst = JsonConvert.DeserializeObject<List<StatsViewModel>>
      (JsonConvert.SerializeObject(listFromDatabase));

      item = targetlst.FirstOrDefault();
      return item;
   }