尝试使用通用<t>集合

时间:2016-02-05 12:46:47

标签: c# asp.net-mvc generics

我正在使用C#,我认为我终于有机会了解Generic类型。我有几个强类型对象需要相同的静态方法。而不是为每种类型创建一个静态方法,我认为我可以使它成为通用的。我从未做过的事情也非常想要。

这是我调用它的地方。

   bool isDuplicate = Utilities.GetDuplicates<RoomBookingModel>(roomBookings);

这是我的静态方法,它位于名为Utilities的静态类中。

 public static bool GetDuplicates<T>(List<T> pBookings)
    {           
        foreach (var item in pBookings)
        {
            var myVal = item.bookingId
        }
        return true;
    }

所以我想得到foreach循环中var项目中的值,这样我就可以进行比较了。它肯定会通过pBookings,因为我可以悬停,他们有一个.Count()与我的强类型对象的集合。我在这里遗漏了一些东西,可能是一个铸造过程。我想知道是否有人可以告诉我我的空缺时间。

var myVal = item.bookingId - 我无法从item获取bookingID,因为我在这里缺乏一些基本的理解。 bookingId不存在,我只能访问扩展方法,如.toString和.equals

回答“ 我根据你所有真正有用的帮助做了什么。我使用了Anderson Pimentel。我可能仍然不合时宜,但想在这里获得任何想法。

所以基本上我有几个预订模型,都需要检查重复项。我真的想以这种方式理解泛型。所以我做的是。创建了一个基类。

public class BookingBaseModel
{
    public int BookingID { get; set; }
    public DateTime BookingStartDateTime { get; set; }
    public DateTime BookingEndDateTime { get; set; }
}

然后我的预订课程都继承了所有人共有的东西。像这样......

public class RoomBookingModel : BookingBaseModel
{
    public string RoomName{ get; set; }
}

public class vehicleBookingModel : BookingBaseModel
{
    public string vehicleName{ get; set; }
}

然后在我的实用程序静态助手中我做了这个..

 public static void GetDuplicates<T>(List<T> items) where T : BookingBaseModel
    {
        foreach (var item in items)
        {
            int myId = item.ID;
            DateTime startDateTime = item.BookingStartDateTime;
            DateTime endDateTime = item.BookingEndDateTime;

            //Do you logic here
        }
    }

然后最终在相应的控制器动作中做了类似的事情。

... RoomController

        Utilities.GetDuplicates<RoomBookingModel>(roomBookings);

... VehicleController

        Utilities.GetDuplicates<VehicleBookingModel>(vehicleBookings);

这基本上是我们以这种方式使用泛型的方式吗?

7 个答案:

答案 0 :(得分:1)

编译器没有提示T的类型。如果您有一个具有bookingId属性的基类(或接口),如BaseModel,则可以约束泛型类型,如下所示:

public class BaseModel
{
    public int Id { get; set; }
}

public static bool GetDuplicates<T>(List<T> items) where T : BaseModel
{           
    foreach (var item in items)
    {
        var myId = item.Id;
        //Do you logic here
    }
    return true;
}

答案 1 :(得分:1)

进入GetDuplicates方法后,您已经失去了RoomBookingModel类型的所有知识。这就是通用方法的要点 - 它们应该能够对传递给它们的任何类型采取行动,例如:其中的逻辑应该是任何类型的通用。

所以你的foreach循环很好 - 你知道你已经得到了一些东西,你知道列表可以迭代。但在foreach内,item只是T。你不知道它是什么实际类型,因为任何类型都可以传入。所以从item访问特定属性或方法是没有意义的 - 例如,如果我调用{{ 1}}传入GetDuplicates?它不会有List<int>属性。

答案 2 :(得分:1)

正如其他人所写,你对T一无所知。 LINQ使用的经典解决方案(例如参见GroupBy)是让您的方法接收一个执行密钥提取的委托,例如:

public static bool GetDuplicates<T, TKey>(List<T> pBookings, Func<T, TKey> selector) 
{
    foreach (var item in pBookings) 
    {
        TKey key = selector(item);
    }

    return true;
}

然后使用它:

GetDuplicates(pBookings, p => p.bookingId);

答案 3 :(得分:1)

我想知道仿制药是否真的是这里工作的工具。如果每个强类型对象共享一个公共接口,那么您的需求会更好。

  

&#34;我有几个需要相同静态方法的强类型对象。&#34;

在这种情况下,所有类必须共享一个共同的功能,例如,属性BookingId

所以,你需要通过提取这个通用界面来形式化这个:

public interface IBooking
{
    int BookingId{ get; }
}

确保每个强类型项都实现接口:

public class RoomBooking : IBooking
{
    //etc...
}

现在让你的静态方法接受IBooking个实例:

public static bool GetDuplicates(IEnumerable<IBooking> pBookings)
{
    //does pBookings contain items with duplicate BookingId values?
    return pBookings.GroupBy(b => b.BookingId).Any(g => g.Count() > 1);
}

通过不必要地使用泛型而不会弄乱的简单阅读。

答案 4 :(得分:1)

如果你想使用泛型方法,你还必须提供一个泛型方法,它能够生成指定类型T之外的密钥。幸运的是,我们有LINQ已经提供了构建泛型方法所需的部分:

internal class Extensions
{
    public static IEnumerable<T> GetDuplicates<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
    {
        return source.GroupBy(keySelector)
                     .Where(group => group.Skip(1).Any())
                     .SelectMany(group => group);
    }

    public static bool ContainsDuplicates<T, TKey>(this IEnumerable<T> source, Func<T, TKey> keySelector)
    {
        return GetDuplicates(source, keySelector).Any();
    }
}

通过这个(和类型推断)你可以使用这些方法,例如致电:

var hasDuplicates = roomBookings.ContainsDuplicates(item => item.bookingId);

if(hasDuplicates)
{
    Console.WriteLine("Duplicates found:");

    foreach (var duplicate in roomBookings.GetDuplicates(item => item.bookingId))
    {
        Console.WriteLine(duplicate);
    }
}

答案 5 :(得分:0)

由于T没有约束或提示,编译器没有足够的信息。考虑

bool isDuplicate = Utilities.GetDuplicates<int>(roomBookings);

显然,int没有bookingId成员。

T的每个可能的特定类型都必须具有公共基类或具有bookingId的接口,即使这样,您也必须在方法签名中添加通用约束来访问

答案 6 :(得分:0)

也许你正在寻找这样的东西:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Duplicates
{

    public static class EnumerableExtensions
    {
        public static bool HasDuplicates<T, I>(this IEnumerable<T> enumerable, Func<T, I> identityGetter, IEqualityComparer<I> comparer )
        {
            var hashSet = new HashSet<I>(comparer);
            foreach (var item in enumerable)
            {
                var identity = identityGetter(item);
                if (hashSet.Contains(identity)) return true;
                hashSet.Add(identity);
            }
            return false;
        }

        public static bool HasDuplicates<T, I>(this IEnumerable<T> enumerable, Func<T, I> identityGetter)
        {
            return enumerable.HasDuplicates(identityGetter, EqualityComparer<I>.Default);
        }
    }

    public class Booking
    {
        public int BookingId { get; set; }
        public string BookingName { get; set; }
    }

    public class Customer
    {
        public string CustomerId { get; set; }
        public string Name { get; set; }
    }


    class Program
    {
        static void Main(string[] args)
        {
            var bookings = new List<Booking>()
            {
                new Booking { BookingId = 1, BookingName = "Booking 1" },
                new Booking { BookingId = 1, BookingName = "Booking 1" }
            };

            Console.WriteLine("Q: There are duplicate bookings?. A: {0}", bookings.HasDuplicates(x => x.BookingId));

            var customers = new List<Customer>()
            {
                new Customer { CustomerId = "ALFKI", Name = "Alfred Kiss" },
                new Customer { CustomerId = "ANATR", Name = "Ana Trorroja" }
            };

            Console.WriteLine("Q: There are duplicate customers?. A: {0} ", customers.HasDuplicates(x => x.CustomerId));

        }
    }
}