我想知道是否可以在该对象的扩展方法中实例化一个空对象。
示例:
简单课程
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
}
扩展方法
public static class ExtensionMethods
{
public static void GetTestClass(this TestClass tc, string name)
{
using (SqlConnection cn = new SqlConnection(myConnectionString))
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText= "SELECT Name, Age FROM Person WHERE Name = @Name";
cn.Open();
cmd.Parameters.AddWithValue("@Name", name);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
tc = new TestClass();
tc.Name = name;
tc.Age = int.Parse(dr["Age"]);
}
}
}
}
}
用户将给我一个名字,我想通过这样做验证该名称是否存在......
static void Main(string[] args)
{
TestClass tc = null;
tc.GetTestClass("Some Name");
if (tc == null)
{
Console.WriteLine("Not Found");
}
Console.Read();
}
这可能吗?我当前的代码将原始对象保留为null。我不知道我做错了什么,这是不可能的。
感谢。
答案 0 :(得分:3)
这不起作用,您需要一个返回对象的方法。在扩展方法中分配 this 参数将不会执行您希望它执行的操作,也不会修改tc
变量。
您可能会成为IntelliSense陷阱的牺牲品,是的,它会向您展示GetTestClass()方法。但是你必须编写的代码没有通过右侧代码审查门: p>
tc = tc.GetTestClass("some name");
显然,您需要一个静态工厂方法:
tc = Mumble.CreateTest("some name");
答案 1 :(得分:2)
我同意@Stuart。看起来您希望扩展方法将使用数据库检索的内容覆盖类的当前实例。
您需要删除读取循环中的tc = new TestClass();
或将此扩展类重写为TestClass
上的静态工厂方法,或者可能是TestClassFactory
。
答案 2 :(得分:1)
不 - 这段代码没有意义:
TestClass tc = null;
tc.GetTestClass("Some Name");
这可能看起来应该抛出NullReferenceException
...
好的 - 所以它没有(请参阅http://www.pvle.be/2008/11/extension-methods-and-null-objects/上的示例)但它也没有通过ref
传递tc ...因此它不会更新tc
为你
关于扩展程序的MSDN说:
一般情况下,我们建议你 谨慎地实施扩展方法 只有当你必须。每当 可能的,必须扩展的客户端代码 现有类型应该通过 创建一个派生自的新类型 现有的类型。
http://msdn.microsoft.com/en-us/library/bb383977.aspx
IMO最好将你正在寻找的东西作为某种工厂方法来实现。
或者你可以使用类似的东西:
TestClass tc = new TestClass();
if (tc.TryFillFrom("Some Name"))
{
// do stuff
}
else
{
// handle missing error
}
或者你可以使用FillFrom
方法抛出一些NotFoundException
答案 3 :(得分:1)
这是可能的,但是当您分配给tc
时,赋值仅影响方法内的参数,而不影响传递给该参数的变量。它与传统参数传递的情况没有什么不同:
public static void GetTestClass(TestClass tc, string name) {
...
tc = new TestClass();
...
}
static void Main() {
TestClass tc = null;
GetTestClass(tc, "Some Name");
// The assignment to tc in GetTestClass doesn't affect the tc variable in Main.
...
}
至于解决方案,请避免在空引用上调用扩展方法。这显然令人困惑。只需通过更简单,更传统的习语来获取新对象:
public static TestClass GetTestClass(string name) {
...
TestClass tc = new TestClass();
...
return tc;
}
static void Main() {
TestClass tc = GetTestClass("Some Name");
...
}
答案 4 :(得分:1)
不,这是不可能的。
它只是发送到方法的变量的引用副本,因此您无法更改变量的内容。
无论如何,使用这样的扩展方法并不直观。虽然你可以在空引用上调用扩展方法,但是你的方法依赖它。
只需使用常规静态方法,如果找不到记录,则返回null:
TestClass tc = TestClass.GetTestClass("Some Name");
答案 5 :(得分:0)
我很惊讶每个人都提供静态方法解决方案。如果这是您的类始终实例化的方式,请使用构造函数。这就是他们的目的。如果它不是唯一的方法,那么创建一个空的构造函数并重载它以传递您的参数,当您希望它以这种方式实例化时。我更喜欢这样的两个构造函数
public class TestClass
{
public string Name { get; set; }
public int Age { get; set; }
public TestClass() { }
public TestClass(string name)
{
using (SqlConnection cn = new SqlConnection(myConnectionString))
using (SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText= "SELECT Name, Age FROM Person WHERE Name = @Name";
cn.Open();
cmd.Parameters.AddWithValue("@Name", name);
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
Name = name;
Age = int.Parse(dr["Age"]);
}
}
}
}
}
对我而言,这更为直截了当。当您无权访问类的代码以添加自己的方法时,应使用扩展方法。