我正在使用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);
这基本上是我们以这种方式使用泛型的方式吗?
答案 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));
}
}
}