[已解决问题] 如何抽象下面这两个方法?
提问时间: 2007-11-30 17:42
悬赏分:50 浏览:670 次

 下面两个方法ListDelete(List<BaseDT> details)和ListDelete(BaseDT[] list),这两个方法除了参数以及一小段代码不一样外,其他的都相同。各位高人谁能帮我抽象出一个方法?

我有一个思路,就是定义一个参数为Object类型或DataSet类型的委托,然后在方法中调用这个委托,总是觉得不好,希望高人能提供一个完美方案。

/// <summary>
    /// 删除多条记录。
    /// </summary>
    /// <param name="details">记录集和</param>
    public void ListDelete(List<BaseDT> details)
    {
        bool selfTran = false;

        //事务处理
        this.BeginTran();
        selfTran = true;
        try
        {
            foreach (BaseDT detail in details)
            {
                this.Delete(detail);
            }

            // 提交事务
            if (selfTran)
            {
                this.CommitTran();
            }
        }
        catch (Exception ex)
        {
            // 回滚事务
            if (selfTran == true)
            {
                this.RollBackTran();
            }
            throw ex;
        }
    }

    /// <summary>
    ///  删除多条记录。
    /// </summary>
    /// <par


问题补充:问题是这样的,有两个函数Function1和Function2。这两个函数中有一些代码是相同的例如:
void Function(int x)
{
// 公共操作部分1

Response.Write(x + "");

// 公共操作部分2
}

void Function(string y, int x)
{
// 公共操作部分1

Response.Write(y + x);

// 公共操作部分2
}

在函数Function1和Function2中,“ 公共操作部分1”和“公共操作部分2”是相同的(例如: “公共操作部分1”为开始一个事物,“公共操作部分2”为提交一个事物)只有“Response.Write(x + "");”和“Response.Write(y + x);”是不同的。

我现在想写一个函数FunctionCommon用来处理函数Function1和Function2中的公共部分。

例如
void FunctionCommon(参数列表)
{
// 公共操作部分1

// ...(不同情况下,实现不同)

// 公共操作部分2
}

那么在Function1和Function2中,仅仅需要处理它们独特的部分就可以了。

不知道如何实现这样的抽象。




所有回答(3)
ListDelete(IEnumerable<BaseDT> details) 然后里面用foreach即可。 一般来说,方法的参数用越“抽象”的数据类型越好,这样可以支持更多的数据类型,增加可复用度。而方法的参数越“具体”越好,这样可以让方法的调用者更灵活地使用。
9个月前   回答者:Jeffrey Zhao - 小虾三级
这个时候可以看一下List<BaseDT>和BaseDT[](Array类)有无共性 通过Code Definition Window可以看到 两者的共同接口有:IList, ICollection, IEnumerable 而你的方法名为ListDelete 所以用IList类型参数较好
9个月前   回答者:Anders Cui - 小虾三级
基本上就可以…… 理由:因为两者的实现在你的代码中可以看出,只用到了参数的迭代器的特性,“最小匹配”原则一下,你可以将其指定为IEnumerable。如果有其他需求,可以再放宽要求。 测试: class GenericClass { public static void ListDelete1<T>(T list) where T : IEnumerable<IDB> { foreach (IDB item in list) { item.Delete(); } } public static void ListDelete2<T>(IEnumerable<T> list) where T : IDB { foreach (T item in list) { item.Delete(); } } public static void ListDelete3<T>(T list) where T : IEnumerable { foreach (IDB item in list) { if (item is IDB) (item as IDB).Delete(); //if (i is OtherInterface) // (item as OtherInterface).Delete(); } } public interface IDB { //Other members void Delete(); } public class BaseDT:IDB { public void Delete() { Console.WriteLine("succeed delete!"); } } class Program { static void Main(string[] args) { List<GenericClass.IDB> list1 = new List<GenericClass.IDB>(); list1.Add(new GenericClass.BaseDT()); list1.Add(new GenericClass.BaseDT()); list1.Add(new GenericClass.BaseDT()); list1.Add(new GenericClass.BaseDT()); GenericClass.ListDelete1<IEnumerable<GenericClass.IDB>>(list1); Console.WriteLine("========================"); GenericClass.IDB[] list2 = new GenericClass.IDB[] { new GenericClass.BaseDT(), new GenericClass.BaseDT(), new GenericClass.BaseDT() }; GenericClass.ListDelete1<IEnumerable<GenericClass.IDB>>(list2); Console.WriteLine("========================"); List<GenericClass.IDB> list3 = new List<GenericClass.IDB>(); list3.Add(new GenericClass.BaseDT()); list3.Add(new GenericClass.BaseDT()); list3.Add(new GenericClass.BaseDT()); list3.Add(new GenericClass.BaseDT()); GenericClass.ListDelete2<GenericClass.IDB>(list3); Console.WriteLine("========================"); GenericClass.IDB[] list4 = new GenericClass.IDB[] { new GenericClass.BaseDT(), new GenericClass.BaseDT(), new GenericClass.BaseDT() }; GenericClass.ListDelete2<GenericClass.IDB>(list4); Console.WriteLine("========================"); List<GenericClass.IDB> list5 = new List<GenericClass.IDB>(); list5.Add(new GenericClass.BaseDT()); list5.Add(new GenericClass.BaseDT()); list5.Add(new GenericClass.BaseDT()); list5.Add(new GenericClass.BaseDT()); GenericClass.ListDelete3<IEnumerable>(list5); Console.WriteLine("========================"); GenericClass.IDB[] list6 = new GenericClass.IDB[] { new GenericClass.BaseDT(), new GenericClass.BaseDT(), new GenericClass.BaseDT() }; GenericClass.ListDelete3<IEnumerable>(list6); } } 其实上面的方法也是可以的,只要你对实现IDB的方法实现自己特殊的部分,比如说: public sealed class ClassA : IDB { public string X {get;set;} public string Y {get;set;} public string IDB.GetResult() { return (X+Y); } public sealed class ClassB : IDB { public string X {get;set;} public string IDB.GetResult() { return X; } } } 这样,你统一调用Response.Write(IDB.GetResult());就可以了 这就是最基本的多态啦撒……
9个月前   回答者:volnet(可以叫我大V) - 小虾三级
评论
9个月前   Jeffrey Zhao :
不过看实现用到的是foreach,所以我还是觉得用IEnumerable好,呵呵。而且建议把方法名改成DeleteAll——.NET Framework中很多这样的命名方法。
9个月前   Jeffrey Zhao :
ListDelete<T>(T list):Where T:IEnumerable
这个很奇怪,至少也应该这样吧:
ListDelete<T>(IEnumerable<T> list);
9个月前   volnet(可以叫我大V) :
class Program
{
static void Main(string[] args)
{
List<string> list1 = new List<string>();
Console.WriteLine(GenericClass.ListDelete<List<string>>(list1));

string[] list2 = new string[] { };
Console.WriteLine(GenericClass.ListDelete<Array>(list2));
}
}

class GenericClass
{
public static string ListDelete<T>(T list) where T : IEnumerable
{
if (list is IEnumerable)
{
return "is";
}
else
{
return "not";
}
}
}
9个月前   Jeffrey Zhao :
范型套范型,太夸张了,尽量避免吧,呵呵。.NET中从来没有见过这样的……不知道能否通过FxCop……
9个月前   volnet(可以叫我大V) :
To老赵:
其实实现方法很多的,你说的方法也都很好,我只是换个手法罢了,异曲同工……
至于FxCop……不好说……不甚了解它的判断机制……
不过若内部操作为类似数据库操作这样的,使用ListDelete<T>(IEnumerable<T> list);方案应该会更好吧
@楼主
随手写的未曾想太多,如果不足,楼主自行调整,提供的思路仅供参考……
9个月前   volnet(可以叫我大V) :
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>, IEnumerable
{}
这里就是泛型套泛型哦。:)
9个月前   Jeffrey Zhao :
尽量避免而已,因为实在复杂,真要使用也没有办法。IDictionary的例子很合理,很清晰,应该算是良好的实现。
9个月前   Jeffrey Zhao :
忽然发现你的例子应该不可取,因为你还是没有限制了T是一个强类型的枚举,也就是方法内部是无法操作IEnumerable对象里的类型(BaseDT)的,这和lz的要求相差有些远,至少要IEnumerable<BaseDT>吧,而且这还必须看lz的要求如何。
9个月前   volnet(可以叫我大V) :
TO 楼主:
看完你的问题补充,发现开始不了解你要问的意思了……(可能是理解能力比较有问题)
原来的问题貌似是在删除东西,而现在貌似没看出什么端倪来……
而且貌似也没用到事件委托的必要……
基于接口在这种情况下是对抽象最好的诠释,看上去这种抽象也很容易让人明白,至于泛型,在这里只是因为它可以满足对强类型的验证而显得优势倍加,至于楼主对于事件委托的应用,感觉太抽象了……起码我没看懂……汗……

已经整理了一份新的CODE,更加完整并符合楼主想法(大概是吧),楼主看看……
9个月前   volnet(可以叫我大V) :
其实上面的方法也是可以的,只要你对实现IDB的方法实现自己特殊的部分,比如说:
public sealed class ClassA : IDB
{
public string X {get;set;}
public string Y {get;set;}
public string IDB.GetResult()
{
return (X+Y);
}

public sealed class ClassB : IDB
{
public string X {get;set;}
public string IDB.GetResult()
{
return X;
}
}
}

这样,你统一调用Response.Write(IDB.GetResult());就可以了
这就是最基本的多态啦撒……
   您需要登录以后才能回答!
 

我要提问

我的问题


快到期问题

> 问题排行榜

相关链接