C# 使用Func<&燃气轮机;通过接口?
我有一个已经存在的泛型类C# 使用Func<&燃气轮机;通过接口?,c#,design-patterns,interface,func,solid-principles,C#,Design Patterns,Interface,Func,Solid Principles,我有一个已经存在的泛型类 public class Foo<T> { private T _item; public Foo(T item){ _item = item;} } 公共类Foo { 私人信托基金项目; 公共Foo(T项){u项=项;} } 我必须创建一个方法,该方法将返回T的某个属性。 我在这里看到两种解决方案 创建接口: public const string TestVar = "bar"; public interface INamable {
public class Foo<T>
{
private T _item;
public Foo(T item){ _item = item;}
}
公共类Foo
{
私人信托基金项目;
公共Foo(T项){u项=项;}
}
我必须创建一个方法,该方法将返回T的某个属性。我在这里看到两种解决方案
public const string TestVar = "bar";
public interface INamable { string Name { get; } }
public class Bar : INamable
{
public string Name { get { return TestVar; } }
}
public class Foo<T> where T : INamable
{
private T _item;
public Foo(T item) { _item = item; }
public string GetName() { return this._item.Name; }
}
[TestMethod()]
public void TestInterface()
{
var bar = new Bar();
var foo = new Foo<Bar>(bar);
Assert.AreEqual(TestVar, foo.GetName());
}
公共常量字符串TestVar=“bar”;
公共接口不可命名{string Name{get;}}
公共类酒吧:无法使用
{
公共字符串名称{get{return TestVar;}}
}
公共类Foo,其中T:INamable
{
私人信托基金项目;
公共Foo(T项){u项=项;}
公共字符串GetName(){返回此。\u item.Name;}
}
[TestMethod()]
公共无效测试接口()
{
var bar=新的bar();
var foo=新foo(bar);
AreEqual(TestVar,foo.GetName());
}
public const string TestVar = "bar";
public class Bar
{
public string Name { get { return TestVar; } }
}
public class Foo<T>
{
private T _item;
private Func<T, string> _funcName;
public Foo(T item, Func<T, string> funcName) { _item = item; _funcName = funcName; }
public string GetName() { return _funcName.Invoke(_item); }
}
[TestMethod()]
public void TestFunc()
{
var bar = new Bar();
var foo = new Foo<Bar>(bar, b => b.Name);
Assert.AreEqual(TestVar, foo.GetName());
}
公共常量字符串TestVar=“bar”;
公共类酒吧
{
公共字符串名称{get{return TestVar;}}
}
公开课Foo
{
私人信托基金项目;
私有函数_funcName;
public Foo(T item,Func funcName){{u item=item;\u funcName=funcName;}
公共字符串GetName(){return _funcName.Invoke(_item);}
}
[TestMethod()]
public void TestFunc()
{
var bar=新的bar();
var foo=新foo(bar,b=>b.Name);
AreEqual(TestVar,foo.GetName());
}
几个月前,我使用了第一个解决方案,使用了经典的界面…第一个解决方案(即没有Func)要简单得多。完全不需要调用Func对象来实现各种各样的属性访问器。如果您的接口最终只有一个方法,那么使用
操作
或Func
委托是完全有效的。我觉得那更干净
不过,您不必编写
调用。用括号来称呼它:\u funcName(\u item)
我在重新措辞我的答案,因为从评论中我意识到我不是很清楚
这取决于代码的意图以及谁有责任为类命名(客户机应该知道并指定如何命名类,而类本身应该有名称)。我对@Scorpi0的例子做了一点修改,这样Foo就可以用这个名字做一些事情(它向它打招呼),而不仅仅是返回它
示例1(接口)
接口不可配置{string Name{get;}
与名称相关的类别:不可复制
{
公共字符串名称{get{return“thing”;}
}
另一类与名称有关的内容:不可复制
{
公共字符串名称{get{返回“不同的东西”;}
}
类Foo,其中T:INamable
{
公共字符串问候语(T项){返回“hi”+项;}
}
这里的东西都有一个名字,不考虑Foo。Foo知道如何打招呼,只要他们有一个名字(这是由他们实现INamable接口的合同保证的)。
在这里,您希望保证Foo只对具有名称的事物起作用,并且尝试对其他事物表示欢迎应该是编译器捕获的类型错误
另外,请注意,您正在每个类中封装Name的具体实现。名称可能取决于其类的私有状态
示例2(Func)
classathing{}
类另一个未更新项{}
福班
{
公共字符串问候语(T项,函数命名函数)
{
返回“hi”+命名功能(项目);
}
}
这里的重点是Foo。事物不一定有名字。我想建立一个可以迎接任何事情的类Foo。它是怎么做到的?对于任何类型,调用方都有责任传入一个可以为该类型命名的函数。
在这种情况下,我们不仅没有要求保证T知道它自己的名称,而且我们正在以一种方式构建Foo,只要我们知道如何给它命名,它就可以迎接任何类型。例如,这项工作:
var foo = new Foo<int>();
var res=foo.Greet(2, n=>n.ToString());
var foo=new foo();
var res=foo.Greet(2,n=>n.ToString());
作为这种灵活性的交换,我们放弃了封装。现在名称不再是类的责任来实现,我们(调用方)正在告诉Foo如何为使用它的每个类命名
因此,根据您想要表达的内容,如果您有一个具有名称的对象层次结构,而不考虑Foo,您可以选择一种或另一种方式。在许多情况下,委托对于实现者来说会更方便,因为vb.net和C#编译器都包含使其使用非常方便的功能。接口可以做一些委托不能做的事情(例如,包括开放泛型方法族),并且在某些情况下可能比委托更有效(因为对实现接口的对象的引用可以作为该接口类型传递,而无需创建另一个堆对象来保存它)。然而,编译器支持轻松创建内联委托,虽然没有为单函数接口提供类似的功能,但这一事实为前者提供了一个非常有力的论据。尝试勾勒出将使用此方法的代码(客户端代码):哪种方法更适合使用?另外,如果您试图访问的属性/字段不是公共的,该怎么办?创建另一个类型比使用已有类型更简单吗?嗯?这与接口方法有何不同?客户端还可以以一种完全不涉及Name属性的方式实现接口。我假设Foo
和INamable
在库代码中。现在,客户端必须创建一个条
,该条实现不可编辑
,以便使用
class AThing {}
class AnotherUnrelatedThing {}
class Foo<T>
{
public string Greet(T item, Func<T, string> namingFunction)
{
return "hi " + namingFunction(item);
}
}
var foo = new Foo<int>();
var res=foo.Greet(2, n=>n.ToString());